mirror of
https://gitee.com/antv/g6.git
synced 2024-12-05 05:09:07 +08:00
feat: add label rotate
This commit is contained in:
parent
0ca0dbc301
commit
0b0e749045
305
demos/test.html
305
demos/test.html
@ -46,208 +46,123 @@
|
||||
}
|
||||
</style>
|
||||
<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 = {
|
||||
roots: [
|
||||
"name": "Modeling Methods",
|
||||
"children": [
|
||||
{
|
||||
main: '主指标一',
|
||||
value: 123111,
|
||||
percent: '100%',
|
||||
type: '1',
|
||||
children: [
|
||||
{
|
||||
main: '指标 1',
|
||||
value: 12312,
|
||||
percent: '39%',
|
||||
type: '2',
|
||||
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": "Classification",
|
||||
"children": [
|
||||
{ "name": "Logistic regression" },
|
||||
{ "name": "Linear discriminant analysis" },
|
||||
{ "name": "Rules" },
|
||||
{ "name": "Decision trees" },
|
||||
{ "name": "Naive Bayes" },
|
||||
{ "name": "K nearest neighbor" },
|
||||
{ "name": "Probabilistic neural network" },
|
||||
{ "name": "Support vector machine" }
|
||||
]
|
||||
},
|
||||
],
|
||||
{
|
||||
"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({
|
||||
container: 'mountNode',
|
||||
height: 500,
|
||||
renderer: 'svg',
|
||||
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',
|
||||
G6.registerNode('treeNode', {
|
||||
anchor: [
|
||||
[ 0.5, 0 ],
|
||||
[ 0.5, 1 ]
|
||||
]
|
||||
});
|
||||
tree.node({
|
||||
shape: 'card',
|
||||
});
|
||||
tree.edge({
|
||||
shape: 'polyline',
|
||||
});
|
||||
tree.on('node:click', ev => {
|
||||
const { domEvent, item } = ev;
|
||||
const { target } = domEvent;
|
||||
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 });
|
||||
});
|
||||
}
|
||||
G6.registerEdge('smooth', {
|
||||
getPath(item) {
|
||||
const points = item.getPoints();
|
||||
const start = points[0];
|
||||
const end = points[points.length - 1];
|
||||
const vgap = Math.abs(end.y - start.y);
|
||||
return [
|
||||
[ 'M', start.x, start.y ],
|
||||
[ 'C', start.x , start.y+ vgap / 2, end.x, end.y - vgap / 2, end.x, end.y ]
|
||||
];
|
||||
|
||||
}
|
||||
});
|
||||
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>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -98,7 +98,7 @@
|
||||
"screenshot": "node ./bin/screenshot.js",
|
||||
"start": "npm run dev",
|
||||
"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",
|
||||
"win-dev": "node ./bin/win-dev.js"
|
||||
},
|
||||
|
@ -76,7 +76,7 @@ Shape.registerEdge('common', {
|
||||
let label = this.getLabel(item);
|
||||
const group = item.getGraphicGroup();
|
||||
const model = item.getModel();
|
||||
const { labelOffsetX, labelOffsetY } = model;
|
||||
const { labelOffsetX, labelOffsetY, labelRotate } = model;
|
||||
if (label) {
|
||||
const center = keyShape.getPoint(0.5);
|
||||
if (!center) {
|
||||
@ -101,7 +101,7 @@ Shape.registerEdge('common', {
|
||||
fill: 'white'
|
||||
};
|
||||
const style = model.labelRectStyle ? Util.mix({}, defaultStyle, model.labelRectStyle) : defaultStyle;
|
||||
group.addShape('rect', {
|
||||
const rect = group.addShape('rect', {
|
||||
attrs: Util.mix({}, style, {
|
||||
x: textBox.minX - padding[3],
|
||||
y: textBox.minY - padding[0],
|
||||
@ -109,6 +109,22 @@ Shape.registerEdge('common', {
|
||||
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);
|
||||
}
|
||||
},
|
||||
|
@ -31,7 +31,7 @@ Shape.registerGroup('common', {
|
||||
x = x + margin[0];
|
||||
y = y + margin[1];
|
||||
const model = item.getModel();
|
||||
const { labelOffsetX, labelOffsetY } = model;
|
||||
const { labelOffsetX, labelOffsetY, labelRotate } = model;
|
||||
x = labelOffsetX ? labelOffsetX + x : x;
|
||||
y = labelOffsetY ? labelOffsetY + y : y;
|
||||
const attrs = Util.mix(true, {}, Global.labelStyle, {
|
||||
@ -45,10 +45,13 @@ Shape.registerGroup('common', {
|
||||
} else {
|
||||
Util.mix(attrs, label);
|
||||
}
|
||||
group.addShape('text', {
|
||||
const labelShape = group.addShape('text', {
|
||||
class: 'label',
|
||||
attrs
|
||||
});
|
||||
if (labelRotate) {
|
||||
labelShape.rotate(labelRotate);
|
||||
}
|
||||
},
|
||||
drawKeyShape(item, box) {
|
||||
const { x, y, width, height } = box;
|
||||
|
@ -53,7 +53,7 @@ Shape.registerNode('common', {
|
||||
const group = item.getGraphicGroup();
|
||||
const label = this.getLabel(item);
|
||||
const model = item.getModel();
|
||||
const { labelOffsetX, labelOffsetY } = model;
|
||||
const { labelOffsetX, labelOffsetY, labelRotate } = model;
|
||||
if (Util.isNil(label)) {
|
||||
return;
|
||||
}
|
||||
@ -66,10 +66,14 @@ Shape.registerNode('common', {
|
||||
} else {
|
||||
Util.mix(attrs, label);
|
||||
}
|
||||
return group.addShape('text', {
|
||||
const labelShape = group.addShape('text', {
|
||||
class: 'label',
|
||||
attrs
|
||||
});
|
||||
if (labelRotate) {
|
||||
labelShape.rotate(labelRotate);
|
||||
}
|
||||
return labelShape;
|
||||
},
|
||||
getPath(item) {
|
||||
const size = this.getSize(item);
|
||||
|
@ -28,7 +28,7 @@ describe('edge item test', () => {
|
||||
const edge = graph.find('node2->node1');
|
||||
expect(edge.getTarget().id).equal('node1');
|
||||
});
|
||||
it('labeloffset', () => {
|
||||
it('label offset', () => {
|
||||
const edge = graph.find('node2->node1');
|
||||
graph.update(edge, {
|
||||
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('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', () => {
|
||||
graph.destroy();
|
||||
});
|
||||
|
@ -32,7 +32,7 @@ describe('group item test', () => {
|
||||
it('getInnerEdges', () => {
|
||||
expect(graph.find('group1').getInnerEdges().length).eql(2);
|
||||
});
|
||||
it('labeloffset', () => {
|
||||
it('label offset', () => {
|
||||
const group = graph.find('group1');
|
||||
graph.update(group, {
|
||||
label: 'group1',
|
||||
@ -42,6 +42,14 @@ describe('group item test', () => {
|
||||
expect(group.getLabel().attr('x')).to.almost.eql(87.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', () => {
|
||||
graph.destroy();
|
||||
});
|
||||
|
@ -50,7 +50,7 @@ describe('node item test', () => {
|
||||
41
|
||||
});
|
||||
});
|
||||
it('labeloffset', () => {
|
||||
it('label offset', () => {
|
||||
const node = graph.find('node1');
|
||||
graph.update(node, {
|
||||
label: 'node1',
|
||||
@ -60,6 +60,14 @@ describe('node item test', () => {
|
||||
expect(node.getLabel().attr('x')).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', () => {
|
||||
graph.destroy();
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user