feat: add label rotate

This commit is contained in:
huangtong.ht 2018-09-27 16:14:01 +08:00
parent 0ca0dbc301
commit 0b0e749045
8 changed files with 167 additions and 205 deletions

View File

@ -46,208 +46,123 @@
} }
</style> </style>
<script> <script>
console.log(G6.version);
G6.registerNode('card', {
collapseButtonUrl:
'https://gw.alipayobjects.com/zos/rmsportal/GGzWwlTjflbJHmXhjMXg.svg',
expandButtonUrl:
'https://gw.alipayobjects.com/zos/rmsportal/DzWdTiwanggjaWKwcnWZ.svg',
draw(item) {
const group = item.getGraphicGroup();
const { main, value, percent, type, collapsed, children } = item.getModel();
const width = 170;
const height = 80;
const buttonWidth = 14;
const buttonHeight = 14;
let button = '';
if (children && children.length > 0) {
button =
'<img class="ce-button" src=' +
(collapsed ? this.expandButtonUrl : this.collapseButtonUrl) +
'>';
}
const html = G6.Util.createDOM(`
<div class="card-container">
<h1 class="main-text">${main}</h1>
<p>
<span class="value-text">${value}</span>
<span class="percent-text">${percent}</span>
</p>
</div>
`);
const keyShape = group.addShape('dom', {
attrs: {
x: 0,
y: 0,
width,
height,
html,
},
});
group.addShape('dom', {
attrs: {
x: width / 2 - buttonWidth / 2,
y: height - buttonHeight + 2,
width: buttonWidth,
height: buttonHeight,
html: button,
},
});
return group;
},
anchor: [[0.5, 0], [0.5, 1]],
});
const data = { const data = {
roots: [ "name": "Modeling Methods",
"children": [
{ {
main: '主指标一', "name": "Classification",
value: 123111, "children": [
percent: '100%', { "name": "Logistic regression" },
type: '1', { "name": "Linear discriminant analysis" },
children: [ { "name": "Rules" },
{ { "name": "Decision trees" },
main: '指标 1', { "name": "Naive Bayes" },
value: 12312, { "name": "K nearest neighbor" },
percent: '39%', { "name": "Probabilistic neural network" },
type: '2', { "name": "Support vector machine" }
children: [ ]
{
main: '指标 1.1',
value: 111,
percent: '90%',
type: '3',
children: [
{
main: '指标 1.11',
value: 111,
percent: '90%',
type: '113',
},
{
main: '指标 1.12',
value: 111,
percent: '90%',
type: '14',
},
],
},
{
main: '指标 1.2',
value: 111,
percent: '90%',
type: '4',
children: [
{
main: '指标 1.21',
value: 111,
percent: '90%',
type: '5',
},
{
main: '指标 1.22',
value: 111,
percent: '90%',
type: '6',
},
{
main: '指标 1.23',
value: 111,
percent: '90%',
type: '7',
},
{
main: '指标 1.24',
value: 111,
percent: '90%',
type: '8',
},
],
},
{
main: '指标 1.3',
value: 111,
percent: '90%',
type: '9',
},
{
main: '指标 1.4',
value: 111,
percent: '90%',
type: '10',
},
],
},
{
main: '指标 2',
value: 12312,
percent: '79%',
type: '11',
},
{
main: '指标 3',
value: 12312,
percent: '79%',
type: '12',
},
],
}, },
], {
"name": "Consensus",
"children": [
{
"name": "Models diversity",
"children": [
{ "name": "Different initializations" },
{ "name": "Different parameter choices" },
{ "name": "Different architectures" },
{ "name": "Different modeling methods" },
{ "name": "Different training sets" },
{ "name": "Different feature sets" }
]
},
{
"name": "Methods",
"children": [
{ "name": "Classifier selection" },
{ "name": "Classifier fusion" }
]
},
{
"name": "Common",
"children": [
{ "name": "Bagging" },
{ "name": "Boosting" },
{ "name": "AdaBoost" }
]
}
]
},
{
"name": "Regression",
"children": [
{ "name": "Multiple linear regression" },
{ "name": "Partial least squares" },
{ "name": "Multi-layer feedforward neural network" },
{ "name": "General regression neural network" },
{ "name": "Support vector regression" }
]
}
]
}; };
const tree = new G6.Tree({ G6.registerNode('treeNode', {
container: 'mountNode', anchor: [
height: 500, [ 0.5, 0 ],
renderer: 'svg', [ 0.5, 1 ]
layout: new G6.Layouts.CompactBoxTree({ ]
// direction: 'LR', // 方向LR/RL/H/TB/BT/V
getHGap: function getHGap() /* d */ {
// 横向间距
return 20;
},
getVGap: function getVGap() /* d */ {
// 竖向间距
return 24;
},
direction: 'TB',
}),
fitView: 'tl',
}); });
tree.node({ G6.registerEdge('smooth', {
shape: 'card', getPath(item) {
}); const points = item.getPoints();
tree.edge({ const start = points[0];
shape: 'polyline', const end = points[points.length - 1];
}); const vgap = Math.abs(end.y - start.y);
tree.on('node:click', ev => { return [
const { domEvent, item } = ev; [ 'M', start.x, start.y ],
const { target } = domEvent; [ 'C', start.x , start.y+ vgap / 2, end.x, end.y - vgap / 2, end.x, end.y ]
const { collapsed, type } = item.getModel(); ];
const parent = item.getParent();
if (target.className === 'ce-button') {
if (collapsed) {
tree.update(item, {
collapsed: false,
});
} else {
tree.update(item, {
collapsed: true,
});
}
} else {
// 点击展开某个节点 同级其他节点收起
const children = parent && parent.getModel().children;
if (children && children.length > 0 && type) {
const isHideArr = children.filter(elem => type !== elem.type);
const isShowArr = children.filter(elem => type === elem.type);
isHideArr.forEach(element => {
tree.update(element.id, { collapsed: true });
});
isShowArr.forEach(element => {
tree.update(element.id, { collapsed: false });
});
}
} }
}); });
tree.read(data); const layout = new G6.Layouts.Dendrogram({
"direction": "TB",
"rankSep": 200
});
const tree = new G6.Tree({
id: 'mountNode', // 容器ID
height: window.innerHeight, // 画布高
layout,
fitView: 'autoZoom' // 自动缩放
});
tree.node({
shape: 'treeNode',
size: 8,
label(model) {
if(model.children && model.children.length>0) {
return {
text: model.name,
textAlign: 'right'
};
}
return {
text: model.name,
textAlign: 'left'
};
},
labelRotate: Math.PI / 2,
labelOffsetX(model) {
if(model.children && model.children.length>0) {
return -10;
}
return 10;
}
});
tree.edge({
shape: 'smooth',
label: 'edge label',
labelRotate: Math.PI / 2,
});
tree.read({ roots: [data] });
</script> </script>
</body> </body>
</html> </html>

View File

@ -98,7 +98,7 @@
"screenshot": "node ./bin/screenshot.js", "screenshot": "node ./bin/screenshot.js",
"start": "npm run dev", "start": "npm run dev",
"test": "torch --compile --renderer --recursive ./test/unit", "test": "torch --compile --renderer --recursive ./test/unit",
"test-live": "torch --compile --interactive --watch --recursive ./test/test-spec.js", "test-live": "torch --compile --interactive --watch --recursive ./test/unit/item/*-spec.js",
"watch": "webpack --config webpack-dev.config.js", "watch": "webpack --config webpack-dev.config.js",
"win-dev": "node ./bin/win-dev.js" "win-dev": "node ./bin/win-dev.js"
}, },

View File

@ -76,7 +76,7 @@ Shape.registerEdge('common', {
let label = this.getLabel(item); let label = this.getLabel(item);
const group = item.getGraphicGroup(); const group = item.getGraphicGroup();
const model = item.getModel(); const model = item.getModel();
const { labelOffsetX, labelOffsetY } = model; const { labelOffsetX, labelOffsetY, labelRotate } = model;
if (label) { if (label) {
const center = keyShape.getPoint(0.5); const center = keyShape.getPoint(0.5);
if (!center) { if (!center) {
@ -101,7 +101,7 @@ Shape.registerEdge('common', {
fill: 'white' fill: 'white'
}; };
const style = model.labelRectStyle ? Util.mix({}, defaultStyle, model.labelRectStyle) : defaultStyle; const style = model.labelRectStyle ? Util.mix({}, defaultStyle, model.labelRectStyle) : defaultStyle;
group.addShape('rect', { const rect = group.addShape('rect', {
attrs: Util.mix({}, style, { attrs: Util.mix({}, style, {
x: textBox.minX - padding[3], x: textBox.minX - padding[3],
y: textBox.minY - padding[0], y: textBox.minY - padding[0],
@ -109,6 +109,22 @@ Shape.registerEdge('common', {
height: textBox.maxY - textBox.minY + padding[0] + padding[2] height: textBox.maxY - textBox.minY + padding[0] + padding[2]
}) })
}); });
if (labelRotate) {
const centerX = (textBox.maxX + textBox.minX) / 2;
const centerY = (textBox.maxY + textBox.minY) / 2;
// labelRotate
label.transform([
[ 't', -centerX, -centerY ],
[ 'r', labelRotate, labelRotate ],
[ 't', centerX, centerY ]
]);
rect.transform([
[ 't', -centerX, -centerY ],
[ 'r', labelRotate, labelRotate ],
[ 't', centerX, centerY ]
]);
}
Util.toFront(label); Util.toFront(label);
} }
}, },

View File

@ -31,7 +31,7 @@ Shape.registerGroup('common', {
x = x + margin[0]; x = x + margin[0];
y = y + margin[1]; y = y + margin[1];
const model = item.getModel(); const model = item.getModel();
const { labelOffsetX, labelOffsetY } = model; const { labelOffsetX, labelOffsetY, labelRotate } = model;
x = labelOffsetX ? labelOffsetX + x : x; x = labelOffsetX ? labelOffsetX + x : x;
y = labelOffsetY ? labelOffsetY + y : y; y = labelOffsetY ? labelOffsetY + y : y;
const attrs = Util.mix(true, {}, Global.labelStyle, { const attrs = Util.mix(true, {}, Global.labelStyle, {
@ -45,10 +45,13 @@ Shape.registerGroup('common', {
} else { } else {
Util.mix(attrs, label); Util.mix(attrs, label);
} }
group.addShape('text', { const labelShape = group.addShape('text', {
class: 'label', class: 'label',
attrs attrs
}); });
if (labelRotate) {
labelShape.rotate(labelRotate);
}
}, },
drawKeyShape(item, box) { drawKeyShape(item, box) {
const { x, y, width, height } = box; const { x, y, width, height } = box;

View File

@ -53,7 +53,7 @@ Shape.registerNode('common', {
const group = item.getGraphicGroup(); const group = item.getGraphicGroup();
const label = this.getLabel(item); const label = this.getLabel(item);
const model = item.getModel(); const model = item.getModel();
const { labelOffsetX, labelOffsetY } = model; const { labelOffsetX, labelOffsetY, labelRotate } = model;
if (Util.isNil(label)) { if (Util.isNil(label)) {
return; return;
} }
@ -66,10 +66,14 @@ Shape.registerNode('common', {
} else { } else {
Util.mix(attrs, label); Util.mix(attrs, label);
} }
return group.addShape('text', { const labelShape = group.addShape('text', {
class: 'label', class: 'label',
attrs attrs
}); });
if (labelRotate) {
labelShape.rotate(labelRotate);
}
return labelShape;
}, },
getPath(item) { getPath(item) {
const size = this.getSize(item); const size = this.getSize(item);

View File

@ -28,7 +28,7 @@ describe('edge item test', () => {
const edge = graph.find('node2->node1'); const edge = graph.find('node2->node1');
expect(edge.getTarget().id).equal('node1'); expect(edge.getTarget().id).equal('node1');
}); });
it('labeloffset', () => { it('label offset', () => {
const edge = graph.find('node2->node1'); const edge = graph.find('node2->node1');
graph.update(edge, { graph.update(edge, {
label: 'node2->node1', label: 'node2->node1',
@ -38,6 +38,14 @@ describe('edge item test', () => {
expect(edge.getLabel().attr('x')).to.almost.eql(162.23606797749977); expect(edge.getLabel().attr('x')).to.almost.eql(162.23606797749977);
expect(edge.getLabel().attr('y')).to.almost.eql(136.11803398874991); expect(edge.getLabel().attr('y')).to.almost.eql(136.11803398874991);
}); });
it('label rotate', () => {
const edge = graph.find('node2->node1');
graph.update(edge, {
label: 'node2->node1',
labelRotate: Math.PI / 2
});
expect(edge.getLabel().getMatrix()).to.almost.deep.eql([ 6.123233995736766e-17, 1, 0, -1, 6.123233995736766e-17, 0, 298.3541019662497, -26.118033988749858, 1 ]);
});
it('destroy', () => { it('destroy', () => {
graph.destroy(); graph.destroy();
}); });

View File

@ -32,7 +32,7 @@ describe('group item test', () => {
it('getInnerEdges', () => { it('getInnerEdges', () => {
expect(graph.find('group1').getInnerEdges().length).eql(2); expect(graph.find('group1').getInnerEdges().length).eql(2);
}); });
it('labeloffset', () => { it('label offset', () => {
const group = graph.find('group1'); const group = graph.find('group1');
graph.update(group, { graph.update(group, {
label: 'group1', label: 'group1',
@ -42,6 +42,14 @@ describe('group item test', () => {
expect(group.getLabel().attr('x')).to.almost.eql(87.5); expect(group.getLabel().attr('x')).to.almost.eql(87.5);
expect(group.getLabel().attr('y')).to.almost.eql(57.5); expect(group.getLabel().attr('y')).to.almost.eql(57.5);
}); });
it('label rotate', () => {
const group = graph.find('group1');
graph.update(group, {
label: 'group1',
labelRotate: Math.PI / 2
});
expect(group.getLabel().getMatrix()).to.almost.deep.eql([ 6.123233995736766e-17, 1, 0, -1, 6.123233995736766e-17, 0, 0, 0, 1 ]);
});
it('destroy', () => { it('destroy', () => {
graph.destroy(); graph.destroy();
}); });

View File

@ -50,7 +50,7 @@ describe('node item test', () => {
41 41
}); });
}); });
it('labeloffset', () => { it('label offset', () => {
const node = graph.find('node1'); const node = graph.find('node1');
graph.update(node, { graph.update(node, {
label: 'node1', label: 'node1',
@ -60,6 +60,14 @@ describe('node item test', () => {
expect(node.getLabel().attr('x')).to.almost.eql(10); expect(node.getLabel().attr('x')).to.almost.eql(10);
expect(node.getLabel().attr('y')).to.almost.eql(10); expect(node.getLabel().attr('y')).to.almost.eql(10);
}); });
it('label rotate', () => {
const node = graph.find('node2');
graph.update(node, {
label: 'node2',
labelRotate: Math.PI / 2
});
expect(node.getLabel().getMatrix()).to.almost.deep.eql([ 6.123233995736766e-17, 1, 0, -1, 6.123233995736766e-17, 0, 0, 0, 1 ]);
});
it('destroy', () => { it('destroy', () => {
graph.destroy(); graph.destroy();
}); });