diff --git a/demos/area-chart-node.html b/demos/area-chart-node.html new file mode 100644 index 0000000000..ece3ae89ea --- /dev/null +++ b/demos/area-chart-node.html @@ -0,0 +1,194 @@ + + + + + + + 面积图节点 + + + +
+ + + + \ No newline at end of file diff --git a/demos/bar-chart-node.html b/demos/bar-chart-node.html new file mode 100644 index 0000000000..144fc35a28 --- /dev/null +++ b/demos/bar-chart-node.html @@ -0,0 +1,141 @@ + + + + + + + 环形柱状图节点 + + + +
+ + + + \ No newline at end of file diff --git a/demos/chart-node.html b/demos/chart-node.html new file mode 100644 index 0000000000..47e2170f27 --- /dev/null +++ b/demos/chart-node.html @@ -0,0 +1,936 @@ + + + + + + + 统计图表节点 + + + +
+ + + + \ No newline at end of file diff --git a/demos/collapse-expand-group.html b/demos/collapse-expand-group.html index d3aca772c9..9558df285b 100644 --- a/demos/collapse-expand-group.html +++ b/demos/collapse-expand-group.html @@ -40,6 +40,33 @@ }, modes: { default: [ 'drag-canvas', 'zoom-canvas', 'collapse-expand-group' ] + }, + groupStyle: { + default: { + lineWidth: 2, + stroke: '#A3B1BF', + radius: 10, + lineDash: [ 5, 5 ], + strokeOpacity: 0.9, + fill: '#F3F9FF', + fillOpacity: 0.8, + opacity: 0.8 + }, + hover: { + stroke: '#faad14', + fill: '#ffe58f', + fillOpacity: 0.3, + opacity: 0.3, + lineWidth: 3 + }, + // 收起状态样式 + collapseStyle: { + r: 50, + // lineDash: [ 5, 5 ], + stroke: '#ffa39e', + lineWidth: 3, + fill: '#ffccc7' + } } }); diff --git a/demos/custom-tree-interactive.html b/demos/custom-tree-interactive.html new file mode 100644 index 0000000000..d9ca0c2600 --- /dev/null +++ b/demos/custom-tree-interactive.html @@ -0,0 +1,587 @@ + + + + + + + Document + + +
+ + + + \ No newline at end of file diff --git a/demos/front-edge.html b/demos/front-edge.html index f18494a3ca..915f61b226 100644 --- a/demos/front-edge.html +++ b/demos/front-edge.html @@ -60,7 +60,6 @@ document.getElementById('changeView').addEventListener('click', (evt) => { const edge=graph.findById('edge1') const nodeGroup = graph.get('nodeGroup') - const edgeGroup = graph.get('edgeGroup') const edge1G = edge.get('group') edge1G.toFront() nodeGroup.toBack(); diff --git a/demos/line-chart-node.html b/demos/line-chart-node.html new file mode 100644 index 0000000000..398e3f8bda --- /dev/null +++ b/demos/line-chart-node.html @@ -0,0 +1,194 @@ + + + + + + + 折线图节点 + + + +
+ + + + \ No newline at end of file diff --git a/demos/point-chart-node.html b/demos/point-chart-node.html new file mode 100644 index 0000000000..4fc462169c --- /dev/null +++ b/demos/point-chart-node.html @@ -0,0 +1,173 @@ + + + + + + + 标注图节点 + + + +
+ + + + \ No newline at end of file diff --git a/demos/stacked-bar-chart-node.html b/demos/stacked-bar-chart-node.html new file mode 100644 index 0000000000..542d679043 --- /dev/null +++ b/demos/stacked-bar-chart-node.html @@ -0,0 +1,146 @@ + + + + + + + 堆叠柱状图节点 + + + +
+ + + + \ No newline at end of file diff --git a/package.json b/package.json index a29201b211..e8f38ae3ca 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "screenshot": "node ./bin/screenshot.js", "start": "npm run dev", "test": "torch --compile --renderer --opts test/mocha.opts --recursive ./test/unit", - "test-live": "torch --compile --interactive --watch --opts test/mocha.opts --recursive ./test/unit/behavior/drag-group-spec.js", + "test-live": "torch --compile --interactive --watch --opts test/mocha.opts --recursive ./test/unit/graph/controller/custom-group-spec.js", "test-live-tree": "torch --compile --interactive --watch --opts test/mocha.opts --recursive ./test/unit/graph/tree-graph-spec.js", "test-bugs": "torch --compile --renderer --recursive ./test/bugs", "test-bugs-live": "torch --compile --interactive --watch --recursive ./test/bugs", diff --git a/src/behavior/drag-group.js b/src/behavior/drag-group.js index 512c6cf1ea..d7bade3965 100644 --- a/src/behavior/drag-group.js +++ b/src/behavior/drag-group.js @@ -5,7 +5,7 @@ * @LastEditTime: 2019-08-23 11:13:43 * @Description: 拖动群组 */ -const { merge } = require('lodash'); +const deepMix = require('@antv/util/lib/deep-mix'); const delegateStyle = { fill: '#F3F9FF', @@ -275,7 +275,7 @@ module.exports = { height, x, y, - ...merge({}, delegateStyle, this.delegateStyle) + ...deepMix({}, delegateStyle, this.delegateStyle) }; // 如果delegate是circle @@ -289,7 +289,7 @@ module.exports = { x: cx, y: cy, r, - ...merge({}, delegateStyle, this.delegateStyle) + ...deepMix({}, delegateStyle, this.delegateStyle) } }); self.shapeOrigin = { x: cx, y: cy }; diff --git a/src/behavior/drag-node-with-group.js b/src/behavior/drag-node-with-group.js index b5a6a6361b..aedcf2fd83 100644 --- a/src/behavior/drag-node-with-group.js +++ b/src/behavior/drag-node-with-group.js @@ -5,7 +5,7 @@ * @LastEditTime: 2019-08-23 13:54:53 * @Description: 有group的情况下,拖动节点的Behavior */ -const { merge } = require('lodash'); +const deepMix = require('@antv/util/lib/deep-mix'); const { delegateStyle } = require('../global'); const body = document.body; @@ -15,8 +15,8 @@ module.exports = { updateEdge: true, delegate: true, delegateStyle: {}, - maxMultiple: 1.2, - minMultiple: 0.8 + maxMultiple: 0.9, + minMultiple: 1 }; }, getEvents() { @@ -26,12 +26,16 @@ module.exports = { 'node:dragend': 'onDragEnd', 'canvas:mouseleave': 'onOutOfRange', mouseenter: 'onMouseEnter', - mouseout: 'onMouseOut' + mouseleave: 'onMouseLeave' }; }, onMouseEnter(evt) { const { target } = evt; const groupId = target.get('groupId'); + const type = target.get('type'); + if (type !== 'circle') { + return; + } if (groupId && this.origin) { const graph = this.graph; const customGroupControll = graph.get('customGroupControll'); @@ -47,7 +51,7 @@ module.exports = { * 拖动节点移除Group时的事件 * @param {Event} evt 事件句柄 */ - onMouseOut(evt) { + onMouseLeave(evt) { const { target } = evt; const groupId = target.get('groupId'); if (groupId && this.origin) { @@ -59,7 +63,10 @@ module.exports = { customGroupControll.setGroupStyle(keyShape, 'default'); } - this.inGroupId = null; + + if (!groupId) { + this.inGroupId = null; + } }, onDragStart(e) { if (!this.shouldBegin.call(this, e)) { @@ -93,6 +100,9 @@ module.exports = { const customGroup = customGroupControll.customGroup; const currentGroup = customGroup[groupId].nodeGroup; customGroupControll.setGroupStyle(currentGroup.get('keyShape'), 'hover'); + + // 初始拖动时候,如果是在当前群组中拖动,则赋值为当前groupId + this.inGroupId = groupId; } } else { // 拖动多个节点 @@ -137,13 +147,8 @@ module.exports = { const currentGroup = customGroup[groupId].nodeGroup; const keyShape = currentGroup.get('keyShape'); - const currentGroupBBox = keyShape.getBBox(); - - const delegateShape = this.target.get('delegateShape'); - const { x, y } = delegateShape.getBBox(); - const { minX, minY, maxX, maxY } = currentGroupBBox; - - if (x > maxX || x < minX || y > maxY || y < minY) { + // 当前 + if (this.inGroupId !== groupId) { customGroupControll.setGroupStyle(keyShape, 'default'); } else { customGroupControll.setGroupStyle(keyShape, 'hover'); @@ -224,11 +229,12 @@ module.exports = { // 检测操作的群组中是否包括子群组 const groups = graph.get('groups'); const hasSubGroup = !!groups.filter(g => g.parentId === groupId).length > 0; - const r = width > height ? width / 2 : height / 2 + (hasSubGroup ? 20 : 0); + const addR = hasSubGroup ? 20 : 10; + const r = width > height ? width / 2 : height / 2; const cx = (width + 2 * x) / 2; const cy = (height + 2 * y) / 2; keyShape.attr({ - r: r + groupNodes[groupId].length * 10, + r: r + groupNodes[groupId].length * 10 + addR, x: cx, y: cy }); @@ -247,7 +253,6 @@ module.exports = { // 节点所在的GroupId const { groupId, id } = model; - // console.log(groupId, this.inGroupId) const customGroupControll = graph.get('customGroupControll'); const customGroup = customGroupControll.customGroup; const groupNodes = graph.get('groupNodes'); @@ -262,7 +267,11 @@ module.exports = { const { minX, minY, maxX, maxY } = currentGroupBBox; // 在自己的group中拖动,判断是否拖出了自己的group - if (!(x < maxX * this.maxMultiple && x > minX * this.minMultiple && y < maxY * this.maxMultiple && y > minY * this.minMultiple)) { + // this.inGroupId !== groupId,则说明拖出了原来的group,拖到了其他group上面, + // 则删除item中的groupId字段,同时删除group中的nodeID + if ( + !(x < maxX * this.maxMultiple && x > minX * this.minMultiple && y < maxY * this.maxMultiple && y > minY * this.minMultiple) + || this.inGroupId !== groupId) { // 拖出了group,则删除item中的groupId字段,同时删除group中的nodeID const currentGroupNodes = groupNodes[groupId]; groupNodes[groupId] = currentGroupNodes.filter(node => node !== id); @@ -274,8 +283,10 @@ module.exports = { } // 拖动到其他的group上面 if (this.inGroupId !== groupId) { + + // 拖动新的group后,更新groupNodes及model中的groupId const nodeInGroup = customGroup[this.inGroupId].nodeGroup; - const keyShape = nodeInGroup.get('keyShape'); + const targetKeyShape = nodeInGroup.get('keyShape'); // 将该节点添加到inGroupId中 if (groupNodes[this.inGroupId].indexOf(id) === -1) { groupNodes[this.inGroupId].push(id); @@ -284,7 +295,7 @@ module.exports = { model.groupId = this.inGroupId; // 拖入节点后,根据最新的节点数量,重新计算群组大小 - this.dynamicChangeGroupSize(evt, nodeInGroup, keyShape); + this.dynamicChangeGroupSize(evt, nodeInGroup, targetKeyShape); } customGroupControll.setGroupStyle(keyShape, 'default'); } else if (this.inGroupId && !groupId) { @@ -372,7 +383,7 @@ module.exports = { if (!this.shape) { // 拖动多个 const parent = graph.get('group'); - const attrs = merge({}, delegateStyle, this.delegateStyle); + const attrs = deepMix({}, delegateStyle, this.delegateStyle); if (this.targets.length > 0) { const nodes = graph.findAllByState('node', 'selected'); if (nodes.length === 0) { diff --git a/src/behavior/drag-node.js b/src/behavior/drag-node.js index 4496d808f1..f811668d7b 100644 --- a/src/behavior/drag-node.js +++ b/src/behavior/drag-node.js @@ -5,7 +5,8 @@ * @LastEditTime: 2019-08-22 18:41:45 * @Description: 拖动节点的Behavior */ -const { merge, isString } = require('lodash'); +const isString = require('@antv/util/lib/type/is-string'); +const deepMix = require('@antv/util/lib/deep-mix'); const { delegateStyle } = require('../global'); const body = document.body; @@ -174,7 +175,7 @@ module.exports = { if (!this.shape) { // 拖动多个 const parent = this.graph.get('group'); - const attrs = merge({}, delegateStyle, this.delegateStyle); + const attrs = deepMix({}, delegateStyle, this.delegateStyle); if (this.targets.length > 0) { const { x, y, width, height, minX, minY } = this.calculationGroupPosition(); this.originPoint = { x, y, width, height, minX, minY }; diff --git a/src/graph/controller/customGroup.js b/src/graph/controller/customGroup.js index 1586705e6d..9fd14bf129 100644 --- a/src/graph/controller/customGroup.js +++ b/src/graph/controller/customGroup.js @@ -5,8 +5,8 @@ * @LastEditTime: 2019-08-23 11:44:32 * @Description: Group Controller */ -const { merge, isString } = require('lodash'); - +const isString = require('@antv/util/lib/type/is-string'); +const deepMix = require('@antv/util/lib/deep-mix'); class CustomGroup { getDefaultCfg() { return { @@ -60,7 +60,8 @@ class CustomGroup { // const { cfg = {} } = options; this.graph = graph; window.graph = graph; - this.styles = this.getDefaultCfg(); + const groupStyle = graph.get('groupStyle'); + this.styles = deepMix({}, this.getDefaultCfg(), groupStyle); // 创建的群组集合 this.customGroup = {}; // 群组初始位置集合 @@ -154,12 +155,12 @@ class CustomGroup { const { hover: hoverStyle, default: defaultStyle } = this.styles; if (isString(style)) { if (style === 'default') { - styles = merge({}, defaultStyle); + styles = deepMix({}, defaultStyle); } else if (style === 'hover') { - styles = merge({}, hoverStyle); + styles = deepMix({}, hoverStyle); } } else { - styles = merge({}, defaultStyle, style); + styles = deepMix({}, defaultStyle, style); } for (const s in styles) { keyShape.attr(s, styles[s]); @@ -328,7 +329,7 @@ class CustomGroup { } else { // 更新时候merge配置项 const { groupStyle } = customGroupStyle; - const styles = merge({}, groupStyle, property); + const styles = deepMix({}, groupStyle, property); this.customGroup[groupId] = { nodeGroup: deletage, groupStyle: styles @@ -536,7 +537,7 @@ class CustomGroup { }); // 缓存群组groupId下的edge和临时生成的node节点 - this.delegateInGroup[groupId] = merge({ + this.delegateInGroup[groupId] = deepMix({ sourceOutTargetInEdges, sourceInTargetOutEdges, edgesOuts, @@ -571,7 +572,7 @@ class CustomGroup { const { default: defaultStyle } = this.styles; - // const styles = merge({}, defaultStyle, { x: cx, y: cy }); + // const styles = deepMix({}, defaultStyle, { x: cx, y: cy }); for (const style in defaultStyle) { keyShape.attr(style, defaultStyle[style]); } diff --git a/src/graph/graph.js b/src/graph/graph.js index ec42022b63..c16774d6a0 100755 --- a/src/graph/graph.js +++ b/src/graph/graph.js @@ -3,11 +3,7 @@ * @Date: 2019-06-27 18:12:06 * @LastEditors: moyee * @LastEditTime: 2019-08-22 11:22:16 - * @Description: file content - */ -/** - * @fileOverview graph - * @author huangtonger@aliyun.com + * @Description: Graph */ const { groupBy } = require('lodash'); const G = require('@antv/g/lib'); @@ -200,7 +196,8 @@ class Graph extends EventEmitter { /** * 群组的原始数据 */ - groups: [] + groups: [], + groupStyle: {} }; } diff --git a/test/unit/graph/controller/custom-group-spec.js b/test/unit/graph/controller/custom-group-spec.js index 3c3b7fb49a..4994490ac8 100644 --- a/test/unit/graph/controller/custom-group-spec.js +++ b/test/unit/graph/controller/custom-group-spec.js @@ -594,7 +594,7 @@ describe.only('signle layer group', () => { expect(isVisible).to.be.true; } - expect(keyShape.attr('r')).eql(groupStyle.r); + expect(keyShape.attr('r')).eql(30); expect(keyShape.attr('x')).eql(groupStyle.x); expect(keyShape.attr('y')).eql(groupStyle.y);