From 5025901e459ae49d85210573ad38fb3f3c1d9230 Mon Sep 17 00:00:00 2001 From: king <18310653075@163.com> Date: 星期日, 25 六月 2023 18:48:54 +0800 Subject: [PATCH] 2023-06-25 --- src/menu/components/chart/antv-X6/index.jsx | 420 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 387 insertions(+), 33 deletions(-) diff --git a/src/menu/components/chart/antv-X6/index.jsx b/src/menu/components/chart/antv-X6/index.jsx index 6d20b17..96e04e1 100644 --- a/src/menu/components/chart/antv-X6/index.jsx +++ b/src/menu/components/chart/antv-X6/index.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types' import { is, fromJS } from 'immutable' import { Popover, Tooltip, message } from 'antd' -import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined } from '@ant-design/icons' +import { ToolOutlined, DeleteOutlined, FontColorsOutlined, VerticalAlignTopOutlined, VerticalAlignBottomOutlined, SaveOutlined, ZoomInOutlined, ZoomOutOutlined, OneToOneOutlined, DoubleLeftOutlined, DownloadOutlined } from '@ant-design/icons' import { Graph, Shape } from '@antv/x6' import { Stencil } from '@antv/x6-plugin-stencil' import { Transform } from '@antv/x6-plugin-transform' @@ -11,6 +11,7 @@ import { Keyboard } from '@antv/x6-plugin-keyboard' import { Clipboard } from '@antv/x6-plugin-clipboard' import { History } from '@antv/x6-plugin-history' +import { Export } from '@antv/x6-plugin-export' import MKEmitter from '@/utils/events.js' import asyncComponent from '@/utils/asyncComponent' @@ -87,6 +88,52 @@ } } } + +Graph.registerNode( + 'lane', + { + inherit: 'rect', + markup: [ + { + tagName: 'rect', + selector: 'body', + }, + { + tagName: 'rect', + selector: 'name-rect', + }, + { + tagName: 'text', + selector: 'name-text', + }, + ], + attrs: { + body: { + fill: '#FFF', + stroke: '#5F95FF', + strokeWidth: 1, + }, + 'name-rect': { + width: 200, + height: 30, + fill: '#5F95FF', + stroke: '#fff', + strokeWidth: 1, + x: -1, + }, + 'name-text': { + ref: 'name-rect', + refY: 0.5, + refX: 0.5, + textAnchor: 'middle', + fontWeight: 'bold', + fill: '#fff', + fontSize: 12, + }, + }, + }, + true, +) Graph.registerNode( 'mk-rect', @@ -266,7 +313,16 @@ width: card.width || 24, height: 400, subtype: card.subtype, - name: card.name + name: card.name, + grid: { + visible: true, + type: 'dot', + args: { + color: '#a0a0a0', + thickness: 1 + } + }, + gridType: 'dot' } let _card = { @@ -318,39 +374,44 @@ }, 1000) } - viewrender = () => { - // const { card } = this.state - - // if (card.plot.subtype === 'mindmap') { - // this.ponitrender() - // } else if (card.plot.subtype === 'indentTree') { - // this.indentrender() - // } else if (card.plot.subtype === 'kapmap') { - this.kapmaprender() - // } - } - - kapmaprender = () => { + plotchange = (res) => { const { card } = this.state - // #region 鍒濆鍖栫敾甯� + if ( + card.plot.subtype !== res.plot.subtype || + card.plot.gridType !== res.plot.gridType || + card.plot.backgroundColor !== res.plot.backgroundColor + ) { + let _element = document.getElementById(card.uuid + 'container') + if (_element) { + _element.innerHTML = '' + } + setTimeout(() => { + this.viewrender() + }, 50) + } + + this.updateComponent(res) + } + + viewrender = () => { + const { card } = this.state + + if (card.plot.subtype === 'xflow') { + this.xflowrender() + } else if (card.plot.subtype === 'lane') { + this.lanerender() + // } else if (card.plot.subtype === 'xflow') { + // this.xflowrender() + } + } + + xflowrender = () => { + const { card } = this.state + const graph = new Graph({ container: document.getElementById(card.uuid + 'container'), - // grid: { - // visible: true, - // type: 'doubleMesh', - // args: [ - // { - // color: '#eee', // 涓荤綉鏍肩嚎棰滆壊 - // thickness: 1 // 涓荤綉鏍肩嚎瀹藉害 - // }, - // { - // color: '#ddd', // 娆$綉鏍肩嚎棰滆壊 - // thickness: 1, // 娆$綉鏍肩嚎瀹藉害 - // factor: 4 // 涓绘缃戞牸绾块棿闅� - // } - // ] - // }, + grid: card.plot.grid, scaling: { min: 0.5, max: 2 @@ -358,7 +419,7 @@ autoResize: true, panning: true, background: { - color: '#ffffff' + color: card.plot.backgroundColor || 'transparent' }, mousewheel: { enabled: true, @@ -423,6 +484,7 @@ .use(new Keyboard()) .use(new Clipboard()) .use(new History()) + .use(new Export()) // #region 鍒濆鍖� stencil const stencil = new Stencil({ @@ -596,6 +658,290 @@ this.mkGraph = graph } + + lanerender = () => { + const { card } = this.state + + const graph = new Graph({ + container: document.getElementById(card.uuid + 'container'), + grid: card.plot.grid, + scaling: { + min: 0.5, + max: 2 + }, + autoResize: true, + panning: true, + background: { + color: card.plot.backgroundColor || 'transparent' + }, + mousewheel: { + enabled: true, + zoomAtMousePosition: true, + modifiers: 'ctrl' + }, + connecting: { + router: 'manhattan', + connector: { + name: 'rounded', + args: { + radius: 8 + } + }, + anchor: 'center', + connectionPoint: 'anchor', + allowBlank: false, + snap: { + radius: 20 + }, + createEdge() { + return new Shape.Edge({ + attrs: { + line: { + stroke: '#A2B1C3', + strokeWidth: 2, + targetMarker: { + name: 'block', + width: 12, + height: 8 + } + } + }, + zIndex: 2 + }) + }, + validateConnection({ targetMagnet }) { + return !!targetMagnet + } + }, + highlighting: { + magnetAdsorbed: { + name: 'stroke', + args: { + attrs: { + fill: '#5F95FF', + stroke: '#5F95FF' + } + } + } + }, + translating: { + restrict(cellView) { + const cell = cellView.cell + const parentId = cell.prop('parent') + + if (parentId) { + const parentNode = graph.getCellById(parentId) + if (parentNode) { + return parentNode.getBBox().moveAndExpand({ + x: 0, + y: 30, + width: 0, + height: -30, + }) + } + } + return cell.getBBox() + } + } + }) + + // #region 浣跨敤鎻掍欢 + graph + .use(new Transform({ + resizing: true, + rotating: true + })) + .use(new Selection()) + .use(new Snapline()) + .use(new Keyboard()) + .use(new Clipboard()) + .use(new History()) + .use(new Export()) + + // #region 鍒濆鍖� stencil + const stencil = new Stencil({ + title: '娴佺▼鍥�', + target: graph, + stencilGraphWidth: 180, + stencilGraphHeight: 180, + groups: [ + { + title: '閫氱敤鑺傜偣', + name: 'group1' + }, + { + title: '鑷畾涔�', + name: 'group2', + graphHeight: 120, + layoutOptions: { + rowHeight: 70 + } + } + ], + layoutOptions: { + columns: 2, + columnWidth: 80, + rowHeight: 55 + } + }) + + document.getElementById(card.uuid + 'stencil').appendChild(stencil.container) + + // #region 蹇嵎閿笌浜嬩欢 + graph.bindKey(['meta+c', 'ctrl+c'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.copy(cells) + } + return false + }) + graph.bindKey(['meta+x', 'ctrl+x'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.cut(cells) + } + return false + }) + graph.bindKey(['meta+v', 'ctrl+v'], () => { + if (!graph.isClipboardEmpty()) { + graph.paste({ offset: 32 }) + } + return false + }) + + // undo redo + graph.bindKey(['meta+z', 'ctrl+z'], () => { + if (graph.canUndo()) { + graph.undo() + } + return false + }) + graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => { + if (graph.canRedo()) { + graph.redo() + } + return false + }) + + // 鍒犻櫎鍏冪礌 + graph.bindKey(['backspace', 'delete'], () => { + const cells = graph.getSelectedCells() + if (cells.length) { + graph.removeCells(cells) + this.selectNode = null + this.setState({node: null}) + } + }) + + // 鎺у埗杩炴帴妗╂樉绀�/闅愯棌 + const showPorts = (ports, show) => { + for (let i = 0, len = ports.length; i < len; i += 1) { + ports[i].style.visibility = show ? 'visible' : 'hidden' + } + } + graph.on('node:mouseenter', () => { + const container = document.getElementById(card.uuid + 'container') + const ports = container.querySelectorAll('.x6-port-body') + showPorts(ports, true) + }) + graph.on('node:mouseleave', () => { + const container = document.getElementById(card.uuid + 'container') + const ports = container.querySelectorAll('.x6-port-body') + showPorts(ports, false) + }) + + graph.on('node:click', ({ e, x, y, node, view }) => { + this.selectNode = node + + this.setState({node: node.store.data}) + }) + graph.on('edge:click', ({ e, x, y, edge, view }) => { + this.selectNode = edge + + this.setState({node: edge.store.data}) + + graph.clearTransformWidgets() + }) + graph.on('blank:click', ({ e, x, y }) => { + this.selectNode = null + + this.setState({node: null}) + }) + + const r1 = graph.createNode({ + shape: 'mk-rect', + label: '寮�濮�', + attrs: { + body: { + rx: 20, + ry: 26 + } + } + }) + const r2 = graph.createNode({ + shape: 'mk-rect', + label: '杩囩▼' + }) + const r3 = graph.createNode({ + shape: 'mk-rect', + attrs: { + body: { + rx: 6, + ry: 6 + } + }, + label: '鍙�夎繃绋�' + }) + const r4 = graph.createNode({ + shape: 'mk-polygon', + attrs: { + body: { + refPoints: '0,10 10,0 20,10 10,20' + } + }, + label: '鍐崇瓥' + }) + const r5 = graph.createNode({ + shape: 'mk-polygon', + attrs: { + body: { + refPoints: '10,0 40,0 30,20 0,20' + } + }, + label: '鏁版嵁' + }) + const r6 = graph.createNode({ + shape: 'mk-circle', + label: '杩炴帴' + }) + + stencil.load([r1, r2, r3, r4, r5, r6], 'group1') + + const p1 = graph.createNode({ + shape: 'mk-ellipse', + label: 'ellipse' + }) + const p2 = graph.createNode({ + shape: 'mk-star', + label: '' + }) + + stencil.load([p1, p2], 'group2') + + let data = [{"id":"1","shape":"lane","width":200,"height":500,"position":{"x":60,"y":60},"label":"<Function>"},{"id":"2","shape":"lane","width":200,"height":500,"position":{"x":260,"y":60},"label":"<Function>"},{"id":"3","shape":"lane","width":200,"height":500,"position":{"x":460,"y":60},"label":"<Function>"},{"id":"4","shape":"lane","width":200,"height":500,"position":{"x":660,"y":60},"label":"<Function>"}] + let cells = [] + data.forEach((item) => { + if (item.shape === 'lane-edge') { + cells.push(graph.createEdge(item)) + } else { + cells.push(graph.createNode(item)) + } + }) + graph.resetCells(cells) + graph.zoomToFit({ padding: 10, maxScale: 1 }) + + this.mkGraph = graph + } setTop = () => { if (!this.selectNode) { @@ -629,6 +975,11 @@ save = () => { // let nodes = this.mkGraph.toJSON() + } + + savePicture = () => { + const { card } = this.state + this.mkGraph.exportPNG(card.name, {padding: 20}) } changeProps = (value, key) => { @@ -717,7 +1068,7 @@ <div className="menu-x6-chart-edit-box" style={_style} onClick={this.clickComponent} id={card.uuid}> <Popover overlayClassName="mk-popover-control-wrap" mouseLeaveDelay={0.2} mouseEnterDelay={0.2} content={ <div className="mk-popover-control"> - <ChartCompileForm config={card} plotchange={this.updateComponent}/> + <ChartCompileForm config={card} plotchange={this.plotchange}/> <CopyComponent type="antvG6" card={card}/> <FontColorsOutlined className="style" title="璋冩暣鏍峰紡" onClick={this.changeStyle}/> <DeleteOutlined className="close" title="delete" onClick={() => this.props.deletecomponent(card.uuid)}/> @@ -738,6 +1089,9 @@ <Tooltip title="淇濆瓨"> <SaveOutlined onClick={this.save}/> </Tooltip> + <Tooltip title="瀵煎嚭鍥剧墖"> + <DownloadOutlined onClick={this.savePicture}/> + </Tooltip> </div> <div className="right-tool"> <Tooltip title="鏀惧ぇ"> -- Gitblit v1.8.0