diff --git a/demos/arc-circle.html b/demos/arc-circle.html
new file mode 100644
index 0000000000..50640f9b31
--- /dev/null
+++ b/demos/arc-circle.html
@@ -0,0 +1,60 @@
+
+
+
+
+ 自定义弧形节点
+
+
+
+
+
+
+
diff --git a/demos/collapse-expand-group.html b/demos/collapse-expand-group.html
new file mode 100644
index 0000000000..d3aca772c9
--- /dev/null
+++ b/demos/collapse-expand-group.html
@@ -0,0 +1,141 @@
+
+
+
+
+ 收起/展开群组
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/drag-group.html b/demos/drag-group.html
new file mode 100644
index 0000000000..66b24e3a74
--- /dev/null
+++ b/demos/drag-group.html
@@ -0,0 +1,144 @@
+
+
+
+
+ 拖动群组
+
+
+
+
+
+
+
diff --git a/demos/linePoint.html b/demos/linePoint.html
index 80c7e06bd0..b3ba27d8f5 100644
--- a/demos/linePoint.html
+++ b/demos/linePoint.html
@@ -1,10 +1,3 @@
-
diff --git a/src/behavior/drag-group.js b/src/behavior/drag-group.js
index 24c1034da0..ec1d7f8cfc 100644
--- a/src/behavior/drag-group.js
+++ b/src/behavior/drag-group.js
@@ -2,11 +2,10 @@
* @Author: moyee
* @Date: 2019-07-31 14:36:15
* @LastEditors: moyee
- * @LastEditTime: 2019-08-22 15:06:01
+ * @LastEditTime: 2019-08-23 11:13:43
* @Description: file content
*/
-
-import { merge } from 'lodash';
+const { merge } = require('lodash');
const delegateStyle = {
fill: '#F3F9FF',
@@ -119,7 +118,7 @@ module.exports = {
* @return {boolean} false/true
*/
updatePosition(evt) {
- if (!this.rectPos || !this.delegateShapeBBox) {
+ if (!this.delegateShapeBBox) {
return false;
}
@@ -189,7 +188,8 @@ module.exports = {
// step 1:先修改groupId中的节点位置
const nodeInGroup = groupNodes[groupId];
-
+ const groupOriginBBox = customGroupControll.getGroupOriginBBox(groupId);
+ const delegateShapeBBoxs = this.delegateShapeBBoxs[groupId];
const otherGroupId = [];
nodeInGroup.forEach((nodeId, index) => {
@@ -205,11 +205,9 @@ module.exports = {
};
}
- const groupOriginBBox = customGroupControll.getGroupOriginBBox(groupId);
-
// 群组拖动后节点的位置:deletateShape的最终位置-群组起始位置+节点位置
- const x = this.delegateShapeBBoxs[groupId].x - groupOriginBBox.x + this.nodePoint[index].x;
- const y = this.delegateShapeBBoxs[groupId].y - groupOriginBBox.y + this.nodePoint[index].y;
+ const x = delegateShapeBBoxs.x - groupOriginBBox.x + this.nodePoint[index].x;
+ const y = delegateShapeBBoxs.y - groupOriginBBox.y + this.nodePoint[index].y;
this.nodePoint[index] = {
x, y
@@ -238,7 +236,6 @@ module.exports = {
const cy = (height + 2 * y) / 2;
groupKeyShape.attr('x', cx);
groupKeyShape.attr('y', cy);
-
customGroupControll.setGroupOriginBBox(id, groupKeyShape.getBBox());
});
@@ -288,8 +285,7 @@ module.exports = {
});
self.shapeOrigin = { x: attrs.x, y: attrs.y };
}
- delegateShape.set('capture', false);
- this.rectPos = { ...self.shapeOrigin };
+ // delegateShape.set('capture', false);
self.delegateShapes[groupId] = delegateShape;
self.delegateShapeBBoxs[groupId] = delegateShape.getBBox();
} else {
@@ -299,9 +295,9 @@ module.exports = {
const x = deltaX + shapeOrigin.x;
const y = deltaY + shapeOrigin.y;
- delegateShape.attr({ x, y });
- this.rectPos = { x, y };
-
+ // 将Canvas坐标转成视口坐标
+ const point = graph.getPointByCanvas(x, y);
+ delegateShape.attr({ x: point.x, y: point.y });
self.delegateShapeBBoxs[groupId] = delegateShape.getBBox();
}
diff --git a/src/behavior/drag-node-with-group.js b/src/behavior/drag-node-with-group.js
index 3c8697326c..cebe176fd5 100644
--- a/src/behavior/drag-node-with-group.js
+++ b/src/behavior/drag-node-with-group.js
@@ -2,10 +2,9 @@
* @Author: moyee
* @Date: 2019-06-27 18:12:06
* @LastEditors: moyee
- * @LastEditTime: 2019-08-22 18:43:16
- * @Description: file content
+ * @LastEditTime: 2019-08-23 13:54:53
+ * @Description: 有group的情况下,拖动节点的Behavior
*/
-const { mix } = require('../util');
const { merge } = require('lodash');
const { delegateStyle } = require('../global');
const body = document.body;
@@ -228,6 +227,8 @@ module.exports = {
x: cx,
y: cy
});
+
+ customGroupControll.setGroupOriginBBox(groupId, keyShape.getBBox());
}
if (keyShape) {
@@ -344,29 +345,6 @@ module.exports = {
this.graph.paint();
}
},
- _updateDelegate1(item, x, y) {
- const self = this;
- let shape = item.get('delegateShape');
- const bbox = item.get('keyShape').getBBox();
- if (!shape) {
- const parent = self.graph.get('group');
- const attrs = mix({}, delegateStyle, this.delegateStyle);
- // model上的x, y是相对于图形中心的,delegateShape是g实例,x,y是绝对坐标
- shape = parent.addShape('rect', {
- attrs: {
- width: bbox.width,
- height: bbox.height,
- x: x - bbox.width / 2,
- y: y - bbox.height / 2,
- ...attrs
- }
- });
- shape.set('capture', false);
- item.set('delegateShape', shape);
- }
- shape.attr({ x: x - bbox.width / 2, y: y - bbox.height / 2 });
- this.graph.paint();
- },
/**
* 更新拖动元素时的delegate
* @param {Event} e 事件句柄
diff --git a/src/behavior/index.js b/src/behavior/index.js
index cb68468b66..49c3678f8c 100644
--- a/src/behavior/index.js
+++ b/src/behavior/index.js
@@ -19,7 +19,7 @@ const behaviors = {
'brush-select': require('./brush-select'),
'drag-group': require('./drag-group'),
'drag-node-with-group': require('./drag-node-with-group'),
- 'collspse-expand-group': require('./collapse-expand-group')
+ 'collapse-expand-group': require('./collapse-expand-group')
};
Util.each(behaviors, (behavior, type) => {
Behavior.registerBehavior(type, behavior);
diff --git a/src/graph/controller/customGroup.js b/src/graph/controller/customGroup.js
index 3191790691..ff4a208edd 100644
--- a/src/graph/controller/customGroup.js
+++ b/src/graph/controller/customGroup.js
@@ -2,12 +2,12 @@
* @Author: moyee
* @Date: 2019-07-30 12:10:26
* @LastEditors: moyee
- * @LastEditTime: 2019-08-22 18:41:33
+ * @LastEditTime: 2019-08-23 11:44:32
* @Description: file content
*/
-import { merge, isString } from 'lodash';
+const { merge, isString } = require('lodash');
-export default class CustomGroup {
+class CustomGroup {
getDefaultCfg() {
return {
default: {
@@ -15,7 +15,7 @@ export default class CustomGroup {
stroke: '#A3B1BF',
radius: 10,
lineDash: [ 5, 5 ],
- strokeOpacity: 0.92,
+ strokeOpacity: 0.9,
fill: '#F3F9FF',
fillOpacity: 0.8,
opacity: 0.8
@@ -367,15 +367,22 @@ export default class CustomGroup {
* @param {string} tmpNodeId 临时节点ID
*/
setGroupTmpNode(groupId, tmpNodeId) {
- // TODO 需要调整
const graph = this.graph;
const graphNodes = graph.get('groupNodes');
const groups = graph.get('groups');
- for (const data of groups) {
- if (data.parentId === groupId) {
- graphNodes[groupId].push(tmpNodeId);
- this.setGroupTmpNode(data.parentId);
- }
+ if (graphNodes[groupId].indexOf(tmpNodeId) < 0) {
+ graphNodes[groupId].push(tmpNodeId);
+ }
+ // 获取groupId的父群组
+ const parentGroup = groups.filter(g => g.id === groupId);
+ let parentId = null;
+ if (parentGroup.length > 0) {
+ parentId = parentGroup[0].parentId;
+ }
+
+ // 如果存在父群组,则把临时元素也添加到父群组中
+ if (parentId) {
+ this.setGroupTmpNode(parentId, tmpNodeId);
}
}
/**
@@ -385,6 +392,7 @@ export default class CustomGroup {
* @memberof ItemGroup
*/
collapseGroup(id) {
+ const self = this;
const customGroup = this.getDeletageGroupById(id);
const { nodeGroup, groupStyle } = customGroup;
@@ -406,6 +414,9 @@ export default class CustomGroup {
// 收起群组时候动画
keyShape.animate({
onFrame(ratio) {
+ if (ratio === 1) {
+ self.setGroupOriginBBox(id, keyShape.getBBox());
+ }
return {
r: groupStyle.r - ratio * (groupStyle.r - r)
};
@@ -445,13 +456,12 @@ export default class CustomGroup {
};
// 将临时添加的节点加入到群组中,以便拖动节点时候线跟着拖动
- nodesInGroup.push(`${id}-custom-node`);
- // this.setGroupTmpNode(id, `${id}-custom-node`);
+ // nodesInGroup.push(`${id}-custom-node`);
+ this.setGroupTmpNode(id, `${id}-custom-node`);
this.updateEdgeInGroupLinks(id, sourceOutTargetInEdges, sourceInTargetOutEdges);
}
-
// 获取群组中节点之间的所有边
const edgeAllInGroup = edges.filter(edge => {
const model = edge.getModel();
@@ -538,6 +548,7 @@ export default class CustomGroup {
*/
expandGroup(id) {
const graph = this.graph;
+ const self = this;
const autoPaint = graph.get('autoPaint');
graph.setAutoPaint(false);
@@ -560,12 +571,16 @@ export default class CustomGroup {
// keyShape.attr('r', groupStyle.r + nodesInGroup.length * 10);
keyShape.animate({
onFrame(ratio) {
+ if (ratio === 1) {
+ self.setGroupOriginBBox(id, keyShape.getBBox());
+ }
return {
r: 30 + ratio * (groupStyle.r + nodesInGroup.length * 10 - 30)
};
}
}, 1000, 'easeCubic');
+ // this.setGroupOriginBBox(id, keyShape.getBBox());
// 群组动画一会后再显示节点和边
setTimeout(() => {
nodesInGroup.forEach(nodeId => {
@@ -590,7 +605,7 @@ export default class CustomGroup {
// 获取群组中节点之间的所有边
const edgeAllInGroup = edges.filter(edge => {
const model = edge.getModel();
- return nodesInGroup.includes(model.source) && nodesInGroup.includes(model.target);
+ return nodesInGroup.includes(model.source) || nodesInGroup.includes(model.target);
});
edgeAllInGroup.forEach(edge => {
@@ -632,9 +647,8 @@ export default class CustomGroup {
// 删除群组中的临时节点ID
const tmpNodeModel = delegateNode.getModel();
- const index = nodesInGroup.indexOf(tmpNodeModel.id);
- nodesInGroup.splice(index, 1);
+ this.deleteTmpNode(id, tmpNodeModel.id);
graph.remove(delegateNode);
delete this.delegateInGroup[id];
}
@@ -642,6 +656,27 @@ export default class CustomGroup {
graph.paint();
}
+ deleteTmpNode(groupId, tmpNodeId) {
+ const graph = this.graph;
+ const groups = graph.get('groups');
+ const nodesInGroup = graph.get('groupNodes')[groupId];
+
+ const index = nodesInGroup.indexOf(tmpNodeId);
+ nodesInGroup.splice(index, 1);
+
+ // 获取groupId的父群组
+ const parentGroup = groups.filter(g => g.id === groupId);
+ let parentId = null;
+ if (parentGroup.length > 0) {
+ parentId = parentGroup[0].parentId;
+ }
+
+ // 如果存在父群组,则把临时元素也添加到父群组中
+ if (parentId) {
+ this.deleteTmpNode(parentId, tmpNodeId);
+ }
+ }
+
/**
* 拆分群组
*
@@ -687,3 +722,5 @@ export default class CustomGroup {
this.delegateInGroup = {};
}
}
+
+module.exports = CustomGroup;
diff --git a/src/graph/controller/index.js b/src/graph/controller/index.js
index 2d831abc49..16a7fd9eca 100644
--- a/src/graph/controller/index.js
+++ b/src/graph/controller/index.js
@@ -4,5 +4,5 @@ module.exports = {
Mode: require('./mode'),
Item: require('./item'),
State: require('./state'),
- CustomGroup: require('./customGroup').default
+ CustomGroup: require('./customGroup')
};
diff --git a/src/graph/graph.js b/src/graph/graph.js
index 1f81876f68..7f0919b5c1 100755
--- a/src/graph/graph.js
+++ b/src/graph/graph.js
@@ -9,7 +9,7 @@
* @fileOverview graph
* @author huangtonger@aliyun.com
*/
-import { groupBy } from 'lodash';
+const { groupBy } = require('lodash');
const G = require('@antv/g/lib');
const EventEmitter = G.EventEmitter;
const Util = require('../util');
diff --git a/test/unit/graph/graph-group-spec.js b/test/unit/graph/graph-group-spec.js
index 9c2c056ddf..d744923212 100644
--- a/test/unit/graph/graph-group-spec.js
+++ b/test/unit/graph/graph-group-spec.js
@@ -2,7 +2,7 @@
* @Author: moyee
* @Date: 2019-07-31 11:54:41
* @LastEditors: moyee
- * @LastEditTime: 2019-08-22 15:47:52
+ * @LastEditTime: 2019-08-23 14:16:27
* @Description: file content
*/
const expect = require('chai').expect;
@@ -12,6 +12,21 @@ const div = document.createElement('div');
div.id = 'graph-group-spec';
document.body.appendChild(div);
+G6.registerNode('circleNode', {
+ drawShape(cfg, group) {
+ const keyShape = group.addShape('circle', {
+ attrs: {
+ x: 0,
+ y: 0,
+ r: 30,
+ fill: '#87e8de'
+ }
+ });
+
+ return keyShape;
+ }
+}, 'circle');
+
describe('graph group', () => {
const graph = new G6.Graph({
container: div,
@@ -19,7 +34,13 @@ describe('graph group', () => {
height: 1000,
pixelRatio: 2,
modes: {
- default: [ 'drag-group', 'click-select', 'drag-node-with-group', 'collspse-expand-group' ]
+ default: [ 'zoom-canvas', 'drag-group', 'click-select', 'drag-node-with-group', 'collapse-expand-group' ]
+ },
+ defaultNode: {
+ shape: 'circleNode'
+ },
+ defaultEdge: {
+ color: '#bae7ff'
}
});
@@ -87,8 +108,7 @@ describe('graph group', () => {
groupId: 'group3',
label: 'rect',
x: 100,
- y: 300,
- shape: 'rect'
+ y: 300
},
{
id: 'node1',
@@ -121,6 +141,7 @@ describe('graph group', () => {
{
id: 'node7',
groupId: 'p1',
+ label: 'node7-p1',
x: 200,
y: 200
},