diff --git a/packages/x6/src/graph/graph.ts b/packages/x6/src/graph/graph.ts index d17f2a98ea1..b3a521f06e0 100644 --- a/packages/x6/src/graph/graph.ts +++ b/packages/x6/src/graph/graph.ts @@ -648,12 +648,6 @@ export class Graph extends Basecoat { return this } - /** - * **Deprecation Notice:** `scale` is deprecated and will be moved in next - * major release. Use `zoom()` instead. - * - * @deprecated - */ scale(): Dom.Scale scale(sx: number, sy?: number, cx?: number, cy?: number): this scale(sx?: number, sy: number = sx as number, cx = 0, cy = 0) { diff --git a/packages/x6/src/index.less b/packages/x6/src/index.less index e8e985c5f5a..f038d4064a3 100644 --- a/packages/x6/src/index.less +++ b/packages/x6/src/index.less @@ -12,3 +12,6 @@ @import './addon/transform/index'; @import './addon/knob/index'; @import './graph/print'; + +// tools +@import './registry/tool/editor'; diff --git a/packages/x6/src/registry/tool/editor.less b/packages/x6/src/registry/tool/editor.less new file mode 100644 index 00000000000..33355e4947d --- /dev/null +++ b/packages/x6/src/registry/tool/editor.less @@ -0,0 +1,21 @@ +@import '../../style/index'; + +.@{x6-prefix}-cell-tool-editor { + position: relative; + display: inline-block; + min-height: 1em; + margin: 0; + padding: 0; + line-height: 1; + white-space: normal; + text-align: center; + vertical-align: top; + overflow-wrap: normal; + outline: none; + transform-origin: 0 0; + -webkit-user-drag: none; +} +.@{x6-prefix}-edge-tool-editor { + border: 1px solid #275fc5; + border-radius: 2px; +} diff --git a/packages/x6/src/registry/tool/editor.ts b/packages/x6/src/registry/tool/editor.ts new file mode 100644 index 00000000000..818d10e4a6d --- /dev/null +++ b/packages/x6/src/registry/tool/editor.ts @@ -0,0 +1,230 @@ +import { ToolsView } from '../../view/tool' +import { Cell, Edge } from '../../model' +import { CellView, NodeView, EdgeView } from '../../view' +import { Point } from '../../geometry' +import { Dom, FunctionExt } from '../../util' + +export class CellEditor extends ToolsView.ToolItem< + NodeView | EdgeView, + CellEditor.CellEditorOptions & { event: JQuery.MouseEventBase } +> { + private editor: HTMLDivElement + private labelIndex = -1 + private distance = 0.5 + + render() { + this.createElement() + this.update() + this.autoFocus() + this.delegateDocumentEvents(this.options.documentEvents!) + + return this + } + + createElement() { + const { cell } = this + const classNames = [ + this.prefixClassName(`${cell.isEdge() ? 'edge' : 'node'}-tool-editor`), + this.prefixClassName('cell-tool-editor'), + ] + this.editor = ToolsView.createElement('div', false) as HTMLDivElement + this.addClass(classNames, this.editor) + this.editor.contentEditable = 'true' + this.container.appendChild(this.editor) + } + + update() { + const { graph, cell, editor } = this + const style = editor.style + + // set tool position + let pos = new Point() + let minWidth = 20 + if (cell.isNode()) { + pos = cell.getBBox().center + minWidth = cell.size().width - 4 + } else if (cell.isEdge()) { + const e = this.options.event + const target = e.target + const parent = target.parentElement + const isEdgeLabel = + parent && Dom.hasClass(parent, this.prefixClassName('edge-label')) + if (isEdgeLabel) { + const index = parent.getAttribute('data-index') || '0' + this.labelIndex = parseInt(index, 10) + const matrix = parent.getAttribute('transform') + const { translation } = Dom.parseTransformString(matrix) + pos = new Point(translation.tx, translation.ty) + minWidth = Dom.getBBox(target).width + } else { + pos = graph.clientToLocal(Point.create(e.clientX, e.clientY)) + const view = this.cellView as EdgeView + const d = view.path.closestPointLength(pos) + this.distance = d + } + } + pos = graph.localToGraph(pos) + style.left = `${pos.x}px` + style.top = `${pos.y}px` + style.minWidth = `${minWidth}px` + + // set tool transform + const scale = graph.scale() + style.transform = `scale(${scale.sx}, ${scale.sy}) translate(-50%, -50%)` + + // set font style + const attrs = this.options.attrs + style.fontSize = `${attrs.fontSize}px` + style.fontFamily = attrs.fontFamily + style.color = attrs.color + style.backgroundColor = attrs.backgroundColor + + // set init value + const getText = this.options.getText + let text + if (typeof getText === 'function') { + text = FunctionExt.call(getText, this.cellView, { + cell: this.cell, + index: this.labelIndex, + }) + } + editor.innerText = text || '' + + return this + } + + onDocumentMouseDown(e: JQuery.MouseDownEvent) { + if (e.target !== this.editor) { + const cell = this.cell + const value = this.editor.innerText.replace(/\n$/, '') || '' + // set value + const setText = this.options.setText + if (typeof setText === 'function') { + FunctionExt.call(setText, this.cellView, { + cell: this.cell, + value, + index: this.labelIndex, + distance: this.distance, + }) + } + // remove tool + cell.removeTool(cell.isEdge() ? 'edge-editor' : 'node-editor') + this.undelegateDocumentEvents() + } + } + + onDblClick(e: JQuery.DoubleClickEvent) { + e.stopPropagation() + } + + onMouseDown(e: JQuery.MouseDownEvent) { + e.stopPropagation() + } + + autoFocus() { + setTimeout(() => { + this.editor.focus() + this.selectText() + }) + } + + selectText() { + if (window.getSelection) { + const range = document.createRange() + const selection = window.getSelection()! + range.selectNodeContents(this.editor) + selection.removeAllRanges() + selection.addRange(range) + } + } +} + +export namespace CellEditor { + export interface CellEditorOptions extends ToolsView.ToolItem.Options { + attrs: { + fontSize: number + fontFamily: string + color: string + backgroundColor: string + } + getText: ( + this: CellView, + args: { + cell: Cell + index?: number + }, + ) => string + setText: ( + this: CellView, + args: { + cell: Cell + value: string + index?: number + distance?: number + }, + ) => void + } +} + +export namespace CellEditor { + CellEditor.config({ + tagName: 'div', + isSVGElement: false, + events: { + dblclick: 'onDblClick', + mousedown: 'onMouseDown', + }, + documentEvents: { + mousedown: 'onDocumentMouseDown', + }, + }) +} + +export namespace CellEditor { + export const NodeEditor = CellEditor.define({ + attrs: { + fontSize: 14, + fontFamily: 'Arial, helvetica, sans-serif', + color: '#000', + backgroundColor: '#fff', + }, + getText({ cell }) { + return cell.attr('text/text') + }, + setText({ cell, value }) { + cell.attr('text/text', value) + }, + }) + + export const EdgeEditor = CellEditor.define({ + attrs: { + fontSize: 14, + fontFamily: 'Arial, helvetica, sans-serif', + color: '#000', + backgroundColor: '#fff', + }, + getText({ cell, index }) { + if (index === -1) { + return '' + } + return cell.prop(`labels/${index}/attrs/label/text`) + }, + setText({ cell, value, index, distance }) { + const edge = cell as Edge + if (index === -1) { + edge.appendLabel({ + position: { + distance: distance!, + }, + attrs: { + label: { + text: value, + }, + }, + }) + } else { + edge.prop(`labels/${index}/attrs/label/text`, value) + } + }, + }) +} diff --git a/packages/x6/src/registry/tool/index.ts b/packages/x6/src/registry/tool/index.ts index 80c91a59a84..827e7206096 100644 --- a/packages/x6/src/registry/tool/index.ts +++ b/packages/x6/src/registry/tool/index.ts @@ -7,12 +7,14 @@ import { Vertices } from './vertices' import { Segments } from './segments' import { SourceAnchor, TargetAnchor } from './anchor' import { SourceArrowhead, TargetArrowhead } from './arrowhead' +import { CellEditor } from './editor' export namespace NodeTool { export const presets = { boundary: Boundary, button: Button, 'button-remove': Button.Remove, + 'node-editor': CellEditor.NodeEditor, } export type Definition = ToolsView.ToolItem.Definition @@ -81,6 +83,7 @@ export namespace EdgeTool { 'target-anchor': TargetAnchor, 'source-arrowhead': SourceArrowhead, 'target-arrowhead': TargetArrowhead, + 'edge-editor': CellEditor.EdgeEditor, } export type Definition = NodeTool.Definition diff --git a/packages/x6/src/style/raw.ts b/packages/x6/src/style/raw.ts index 58ee6795d91..964413001d2 100644 --- a/packages/x6/src/style/raw.ts +++ b/packages/x6/src/style/raw.ts @@ -1241,4 +1241,23 @@ export const content = `.x6-graph { display: none; } } +.x6-cell-tool-editor { + position: relative; + display: inline-block; + min-height: 1em; + padding: 0px; + margin: 0px; + line-height: 1; + text-align: center; + outline: none; + white-space: normal; + transform-origin: 0px 0px; + overflow-wrap: normal; + vertical-align: top; + -webkit-user-drag: none; +} +.x6-edge-tool-editor { + border: 1px solid #275FC5; + border-radius: 2px; +} ` diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.env b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.env new file mode 100644 index 00000000000..c91520f694a --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.env @@ -0,0 +1,3 @@ +GENERATE_SOURCEMAP=false +SKIP_PREFLIGHT_CHECK=true +PUBLIC_URL='./' diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.gitignore b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.gitignore new file mode 100644 index 00000000000..db037d53ea6 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/.gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +react-app-env.d.ts +/.pnp +.pnp.js + +# testing +/coverage + +# production +/build + +# misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/package.json b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/package.json new file mode 100644 index 00000000000..23761495f3c --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/package.json @@ -0,0 +1,41 @@ +{ + "name": "@antv/x6-sites-demos-api.registry.node-tool.editor", + "version": "0.1.0", + "private": true, + "dependencies": { + "@antv/x6": "latest", + "@antv/x6-sites-demos-helper": "latest", + "antd": "^4.4.2", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-scripts": "^3.4.1" + }, + "devDependencies": { + "@types/react": "^16.9.19", + "@types/react-dom": "^16.9.5", + "typescript": "^4.1.2" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject", + "deploy": "yarn -s prepare && yarn -s static", + "prestart": "yarn prepare" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } +} diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/public/index.html b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/public/index.html new file mode 100644 index 00000000000..775bb0d85d9 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/public/index.html @@ -0,0 +1,15 @@ + + + + + + + + + +
+ + diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.css b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.css new file mode 100644 index 00000000000..206f2e59a87 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.css @@ -0,0 +1,14 @@ +.app { + font-family: sans-serif; + padding: 0; + display: flex; + padding: 16px 8px; +} + +.app-content { + height: 240px; + flex: 1; + margin-left: 8px; + margin-right: 8px; + box-shadow: 0 0 10px 1px #e9e9e9; +} diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.tsx b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.tsx new file mode 100644 index 00000000000..146926210ce --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/app.tsx @@ -0,0 +1,79 @@ +import React from 'react' +import { Graph } from '@antv/x6' +import './app.css' + +export default class Example extends React.Component { + private container: HTMLDivElement + + componentDidMount() { + const graph = new Graph({ + container: this.container, + grid: true, + connecting: { + connector: 'smooth', + }, + }) + + const source = graph.addNode({ + x: 40, + y: 40, + width: 80, + height: 40, + label: 'source', + }) + + const target = graph.addNode({ + x: 350, + y: 150, + width: 80, + height: 40, + label: 'target', + }) + + graph.addEdge({ + source, + target, + labels: [ + { + position: 0.3, + attrs: { + label: { + text: 'edge1', + }, + }, + }, + { + position: 0.6, + attrs: { + label: { + text: 'edge2', + }, + }, + }, + ], + }) + + graph.on('cell:dblclick', ({ cell, e }) => { + cell.addTools([ + { + name: cell.isEdge() ? 'edge-editor' : 'node-editor', + args: { + event: e, + }, + }, + ]) + }) + } + + refContainer = (container: HTMLDivElement) => { + this.container = container + } + + render() { + return ( +
+
+
+ ) + } +} diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.css b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.css new file mode 100644 index 00000000000..e2bd8f36a01 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.css @@ -0,0 +1,14 @@ +body { + margin: 0; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', + 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', + sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +code { + font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', + monospace; +} diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.tsx b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.tsx new file mode 100644 index 00000000000..35c93d49f10 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/src/index.tsx @@ -0,0 +1,11 @@ +import React from 'react' +import ReactDOM from 'react-dom' +import App from './app' +import { Wrap } from '@antv/x6-sites-demos-helper' + +ReactDOM.render( + + + , + document.getElementById('root'), +) diff --git a/sites/x6-sites-demos/packages/api/registry/node-tool/editor/tsconfig.json b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/tsconfig.json new file mode 100644 index 00000000000..b46de511b01 --- /dev/null +++ b/sites/x6-sites-demos/packages/api/registry/node-tool/editor/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "allowJs": true, + "strict": true, + "isolatedModules": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "strictPropertyInitialization": false, + "noEmit": true, + "module": "esnext", + "moduleResolution": "node", + "sourceMap": true, + "declaration": true, + "skipLibCheck": true, + "esModuleInterop": true, + "noImplicitAny": true, + "noEmitOnError": true, + "noUnusedLocals": true, + "strictNullChecks": true, + "resolveJsonModule": true, + "experimentalDecorators": true, + "jsx": "react", + "target": "es5", + "lib": ["dom", "es2015"] + }, + "include": ["src"] +} diff --git a/sites/x6-sites/docs/api/registry/edge-tool.en.md b/sites/x6-sites/docs/api/registry/edge-tool.en.md index 6ef760083fa..4c64566b779 100644 --- a/sites/x6-sites/docs/api/registry/edge-tool.en.md +++ b/sites/x6-sites/docs/api/registry/edge-tool.en.md @@ -67,8 +67,7 @@ graph.on('edge:mouseleave', ({ cell }) => { - [button](#button) 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。 - [button-remove](#button-remove) 在指定的位置处,渲染一个删除按钮,点击时删除对应的边。 - [source-arrowhead-和-target-arrowhead](#source-arrowhead-和-target-arrowhead) 在边的起点或终点渲染一个图形(默认是箭头),拖动该图形来修改边的起点或终点。 - - +- [edge-editor](#edge-editor) 提供边上文本编辑功能。 ## presets @@ -396,6 +395,38 @@ graph.on('edge:mouseleave', ({ cell }) => { +### edge-editor + +提供边上文本编辑功能。 + +参数 + +| 参数名 | 类型 | 默认值 | 说明 | +|---------|---------------------------|-------------|-------------------------------------------------------| +| event | JQuery.MouseEventBase | - | 触发文本编辑的事件参数 | +| attrs/fontSize | string | `14` | 编辑文本字体大小 | +| attrs/color | string | `#000` | 编辑文本字体颜色 | +| attrs/fontFamily | string | `Arial, helvetica, sans-serif`| 编辑文本的字体 | +| attrs/backgroundColor | string | `#fff`| 编辑区域的背景色 | +| getText | (this: CellView, args: {cell: Cell}) => string | - | 获取原文本方法,在自定义 `markup` 场景需要自定义 `getText` 方法 | +| setText | (this: CellView, args: {cell: Cell, value: string}) => void | - | 设置新文本,在自定义 `markup` 场景需要自定义 `setText` 方法 | + +使用 + +```ts +// 双击进入编辑模式 +graph.on('edge:dblclick', ({ cell, e }) => { + cell.addTools({ + name: 'edge-editor', + args: { + event: e, + }, + }) +}) +``` + + + ## registry 我们在 Registry.EdgeTool.registry 对象上提供了注册和取消注册工具的方法,工具实际上是一个继承自 ToolItem 的[视图](/en/docs/api/view/view)。 diff --git a/sites/x6-sites/docs/api/registry/edge-tool.zh.md b/sites/x6-sites/docs/api/registry/edge-tool.zh.md index 75d06e04936..c7d9d9a4aed 100644 --- a/sites/x6-sites/docs/api/registry/edge-tool.zh.md +++ b/sites/x6-sites/docs/api/registry/edge-tool.zh.md @@ -67,9 +67,8 @@ graph.on('edge:mouseleave', ({ cell }) => { - [button](#button) 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。 - [button-remove](#button-remove) 在指定的位置处,渲染一个删除按钮,点击时删除对应的边。 - [source-arrowhead-和-target-arrowhead](#source-arrowhead-和-target-arrowhead) 在边的起点或终点渲染一个图形(默认是箭头),拖动该图形来修改边的起点或终点。 +- [edge-editor](#edge-editor) 提供边上文本编辑功能。 - - ## presets ### vertices @@ -396,6 +395,38 @@ graph.on('edge:mouseleave', ({ cell }) => { +### edge-editor + +提供边上文本编辑功能。 + +参数 + +| 参数名 | 类型 | 默认值 | 说明 | +|---------|---------------------------|-------------|-------------------------------------------------------| +| event | JQuery.MouseEventBase | - | 触发文本编辑的事件参数 | +| attrs/fontSize | string | `14` | 编辑文本字体大小 | +| attrs/color | string | `#000` | 编辑文本字体颜色 | +| attrs/fontFamily | string | `Arial, helvetica, sans-serif`| 编辑文本的字体 | +| attrs/backgroundColor | string | `#fff`| 编辑区域的背景色 | +| getText | (this: CellView, args: {cell: Cell}) => string | - | 获取原文本方法,在自定义 `markup` 场景需要自定义 `getText` 方法 | +| setText | (this: CellView, args: {cell: Cell, value: string}) => void | - | 设置新文本,在自定义 `markup` 场景需要自定义 `setText` 方法 | + +使用 + +```ts +// 双击进入编辑模式 +graph.on('edge:dblclick', ({ cell, e }) => { + cell.addTools({ + name: 'edge-editor', + args: { + event: e, + }, + }) +}) +``` + + + ## registry 我们在 Registry.EdgeTool.registry 对象上提供了注册和取消注册工具的方法,工具实际上是一个继承自 ToolItem 的[视图](/zh/docs/api/view/view)。 diff --git a/sites/x6-sites/docs/api/registry/node-tool.en.md b/sites/x6-sites/docs/api/registry/node-tool.en.md index 357d472ff6b..0bc43fb0797 100644 --- a/sites/x6-sites/docs/api/registry/node-tool.en.md +++ b/sites/x6-sites/docs/api/registry/node-tool.en.md @@ -62,6 +62,7 @@ graph.on('node:mouseleave', ({ node }) => { - [button](#button) 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。 - [button-remove](#button-remove) 在指定的位置处,渲染一个删除按钮,点击时删除对应的节点。 - [boundary](#boundary) 根据节点的包围盒渲染一个包围节点的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。 +- [node-editor](#node-editor) 提供节点文本编辑功能。 ## presets @@ -232,6 +233,38 @@ const source = graph.addNode({ +### node-editor + +提供节点上文本编辑功能。 + +参数 + +| 参数名 | 类型 | 默认值 | 说明 | +|---------|---------------------------|-------------|-------------------------------------------------------| +| event | JQuery.MouseEventBase | - | 触发文本编辑的事件参数 | +| attrs/fontSize | string | `14` | 编辑文本字体大小 | +| attrs/color | string | `#000` | 编辑文本字体颜色 | +| attrs/fontFamily | string | `Arial, helvetica, sans-serif`| 编辑文本的字体 | +| attrs/backgroundColor | string | `#fff`| 编辑区域的背景色 | +| getText | (this: CellView, args: {cell: Cell}) => string | - | 获取原文本方法,在自定义 `markup` 场景需要自定义 `getText` 方法 | +| setText | (this: CellView, args: {cell: Cell, value: string}) => void | - | 设置新文本,在自定义 `markup` 场景需要自定义 `getText` 方法 | + +使用 + +```ts +// 双击进入编辑模式 +graph.on('node:dblclick', ({ cell, e }) => { + node.addTools({ + name: 'node-editor', + args: { + event: e, + }, + }) +}) +``` + + + ## registry 我们在 Registry.NodeTool.registry 对象上提供了注册和取消注册工具的方法,工具实际上是一个继承自 ToolItem 的[视图](/en/docs/api/view/view)。 diff --git a/sites/x6-sites/docs/api/registry/node-tool.zh.md b/sites/x6-sites/docs/api/registry/node-tool.zh.md index f63975f6cd5..2f7139b6a91 100644 --- a/sites/x6-sites/docs/api/registry/node-tool.zh.md +++ b/sites/x6-sites/docs/api/registry/node-tool.zh.md @@ -62,7 +62,7 @@ graph.on('node:mouseleave', ({ node }) => { - [button](#button) 在指定位置处渲染一个按钮,支持自定义按钮的点击交互。 - [button-remove](#button-remove) 在指定的位置处,渲染一个删除按钮,点击时删除对应的节点。 - [boundary](#boundary) 根据节点的包围盒渲染一个包围节点的矩形。注意,该工具仅仅渲染一个矩形,不带任何交互。 - +- [node-editor](#node-editor) 提供节点文本编辑功能。 ## presets @@ -232,6 +232,38 @@ const source = graph.addNode({ +### node-editor + +提供节点上文本编辑功能。 + +参数 + +| 参数名 | 类型 | 默认值 | 说明 | +|---------|---------------------------|-------------|-------------------------------------------------------| +| event | JQuery.MouseEventBase | - | 触发文本编辑的事件参数 | +| attrs/fontSize | string | `14` | 编辑文本字体大小 | +| attrs/color | string | `#000` | 编辑文本字体颜色 | +| attrs/fontFamily | string | `Arial, helvetica, sans-serif`| 编辑文本的字体 | +| attrs/backgroundColor | string | `#fff`| 编辑区域的背景色 | +| getText | (this: CellView, args: {cell: Cell}) => string | - | 获取原文本方法,在自定义 `markup` 场景需要自定义 `getText` 方法 | +| setText | (this: CellView, args: {cell: Cell, value: string}) => void | - | 设置新文本,在自定义 `markup` 场景需要自定义 `setText` 方法 | + +使用 + +```ts +// 双击进入编辑模式 +graph.on('node:dblclick', ({ cell, e }) => { + node.addTools({ + name: 'node-editor', + args: { + event: e, + }, + }) +}) +``` + + + ## registry 我们在 Registry.NodeTool.registry 对象上提供了注册和取消注册工具的方法,工具实际上是一个继承自 ToolItem 的[视图](/zh/docs/api/view/view)。