SV.registerLayouter('BinaryTree', { defineOptions() { return { element: { default: { type: 'binary-tree-node', size: [60, 30], label: '[id]', style: { fill: '#b83b5e', stroke: "#333", cursor: 'pointer' } } }, link: { child: { type: 'line', sourceAnchor: index => index === 0? 3: 1, targetAnchor: 0, style: { stroke: '#333', lineAppendWidth: 6, cursor: 'pointer', endArrow: 'default', startArrow: { path: G6.Arrow.circle(2, -1), fill: '#333' } } } }, pointer: { external: { anchor: 0, offset: 14, style: { fill: '#f08a5d' }, labelOptions: { style: { fill: '#000099' } } } }, layout: { xInterval: 40, yInterval: 40 }, behavior: { // dragNode: false } }; }, /** * 对子树进行递归布局 */ layoutItem(node, parent, index, layoutOptions) { // 次双亲不进行布局 if(!node) { return null; } let bound = node.getBound(), width = bound.width, height = bound.height, group = new Group(node); if(parent) { node.set('y', parent.get('y') + layoutOptions.yInterval + height); // 左节点 if(index === 0) { node.set('x', parent.get('x') - layoutOptions.xInterval / 2 - width / 2); } // 右结点 if(index === 1) { node.set('x', parent.get('x') + layoutOptions.xInterval / 2 + width / 2); } } if(node.child && (node.child[0] || node.child[1])) { let leftChild = node.child[0], rightChild = node.child[1], leftGroup = this.layoutItem(leftChild, node, 0, layoutOptions), rightGroup = this.layoutItem(rightChild, node, 1, layoutOptions), intersection = null, move = 0; // 处理左右子树相交问题 if(leftGroup && rightGroup) { intersection = Bound.intersect(leftGroup.getBound(), rightGroup.getBound()); move = 0; if(intersection && intersection.width > 0) { move = (intersection.width + layoutOptions.xInterval) / 2; leftGroup.translate(-move, 0); rightGroup.translate(move, 0); } } if(leftGroup) { group.add(leftGroup); } if(rightGroup) { group.add(rightGroup) } } return group; }, /** * 布局函数 * @param {*} elements * @param {*} layoutOptions */ layout(elements, layoutOptions) { let root = elements[0]; this.layoutItem(root, null, -1, layoutOptions); } }); [ { "id": 6385328, "data": "", "external": [ "L" ], "root": true, "after": null, "next": null } ]