Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

G6 5.x How to set the canvas position not to move after unfolding #6494

Closed
joshua177 opened this issue Nov 8, 2024 · 5 comments
Closed

G6 5.x How to set the canvas position not to move after unfolding #6494

joshua177 opened this issue Nov 8, 2024 · 5 comments

Comments

@joshua177
Copy link

使用自定义节点展开折叠时,每次点击展开或折叠按钮,画布的位置都会平移一下,如果节点很多,画布移动导致刚刚点击的节点都找不到了,如何设置展开折叠后,画布还保持之前的位置不动?

@github-actions github-actions bot changed the title g6 5.x 如何设置展开折叠后 画布位置不移动 G6 5.x How to set the canvas position not to move after unfolding Nov 8, 2024
@Aarebecca
Copy link
Contributor

可以提供一下复现 demo 吗

@joshua177
Copy link
Author

import { Rect as GRect, Text as GText } from '@antv/g';
import {
Badge,
CommonEvent,
ExtensionCategory,
Graph,
GraphEvent,
iconfont,
Label,
Rect,
register,
treeToGraphData,
} from '@antv/g6';

const style = document.createElement('style');
style.innerHTML = @import url('${iconfont.css}');;
document.head.appendChild(style);

const COLORS = {
B: '#1783FF',
R: '#F46649',
Y: '#DB9D0D',
G: '#60C42D',
DI: '#A7A7A7',
};
const GREY_COLOR = '#CED4D9';

class TreeNode extends Rect {
get data() {
return this.context.model.getNodeLikeDatum(this.id);
}

get childrenData() {
return this.context.model.getChildrenData(this.id);
}

getLabelStyle(attributes) {
const [width, height] = this.getSize(attributes);
return {
x: -width / 2 + 8,
y: -height / 2 + 16,
text: this.data.name,
fontSize: 12,
opacity: 0.85,
fill: '#000',
cursor: 'pointer',
};
}

getPriceStyle(attributes) {
const [width, height] = this.getSize(attributes);
return {
x: -width / 2 + 8,
y: height / 2 - 8,
text: this.data.label,
fontSize: 16,
fill: '#000',
opacity: 0.85,
};
}

drawPriceShape(attributes, container) {
const priceStyle = this.getPriceStyle(attributes);
this.upsert('price', GText, priceStyle, container);
}

getCurrencyStyle(attributes) {
const [, height] = this.getSize(attributes);
return {
x: this.shapeMap['price'].getLocalBounds().max[0] + 4,
y: height / 2 - 8,
text: this.data.currency,
fontSize: 12,
fill: '#000',
opacity: 0.75,
};
}

drawCurrencyShape(attributes, container) {
const currencyStyle = this.getCurrencyStyle(attributes);
this.upsert('currency', GText, currencyStyle, container);
}

getPercentStyle(attributes) {
const [width, height] = this.getSize(attributes);
return {
x: width / 2 - 4,
y: height / 2 - 8,
text: ${((Number(this.data.variableValue) || 0) * 100).toFixed(2)}%,
fontSize: 12,
textAlign: 'right',
fill: COLORS[this.data.status],
};
}

drawPercentShape(attributes, container) {
const percentStyle = this.getPercentStyle(attributes);
this.upsert('percent', GText, percentStyle, container);
}

getTriangleStyle(attributes) {
const percentMinX = this.shapeMap['percent'].getLocalBounds().min[0];
const [, height] = this.getSize(attributes);
return {
fill: COLORS[this.data.status],
x: this.data.variableUp ? percentMinX - 18 : percentMinX,
y: height / 2 - 16,
fontFamily: 'iconfont',
fontSize: 16,
text: '\ue62d',
transform: this.data.variableUp ? [] : [['rotate', 180]],
};
}

drawTriangleShape(attributes, container) {
const triangleStyle = this.getTriangleStyle(attributes);
this.upsert('triangle', Label, triangleStyle, container);
}

getVariableStyle(attributes) {
const [, height] = this.getSize(attributes);
return {
fill: '#000',
fontSize: 12,
opacity: 0.45,
text: this.data.variableName,
textAlign: 'right',
x: this.shapeMap['triangle'].getLocalBounds().min[0] - 4,
y: height / 2 - 8,
};
}

drawVariableShape(attributes, container) {
const variableStyle = this.getVariableStyle(attributes);
this.upsert('variable', GText, variableStyle, container);
}

getCollapseStyle(attributes) {
if (this.childrenData.length === 0) return false;
const { collapsed } = attributes;
const [width, height] = this.getSize(attributes);
return {
backgroundFill: '#fff',
backgroundHeight: 16,
backgroundLineWidth: 1,
backgroundRadius: 0,
backgroundStroke: GREY_COLOR,
backgroundWidth: 16,
cursor: 'pointer',
fill: GREY_COLOR,
fontSize: 16,
text: collapsed ? '+' : '-',
textAlign: 'center',
textBaseline: 'middle',
x: width / 2,
y: 0,
};
}

drawCollapseShape(attributes, container) {
const collapseStyle = this.getCollapseStyle(attributes);
const btn = this.upsert('collapse', Badge, collapseStyle, container);

if (btn && !Reflect.has(btn, '__bind__')) {
  Reflect.set(btn, '__bind__', true);
  btn.addEventListener(CommonEvent.CLICK, () => {
    const { collapsed } = this.attributes;
    const graph = this.context.graph;
    if (collapsed) graph.expandElement(this.id);
    else graph.collapseElement(this.id);
  });
}

}

getProcessBarStyle(attributes) {
const { rate, status } = this.data;
const { radius } = attributes;
const color = COLORS[status];
const percent = ${Number(rate) * 100}%;
const [width, height] = this.getSize(attributes);
return {
x: -width / 2,
y: height / 2 - 4,
width: width,
height: 4,
radius: [0, 0, radius, radius],
fill: linear-gradient(to right, ${color} ${percent}, ${GREY_COLOR} ${percent}),
};
}

drawProcessBarShape(attributes, container) {
const processBarStyle = this.getProcessBarStyle(attributes);
this.upsert('process-bar', GRect, processBarStyle, container);
}

getKeyStyle(attributes) {
const keyStyle = super.getKeyStyle(attributes);
return {
...keyStyle,
fill: '#fff',
lineWidth: 1,
stroke: GREY_COLOR,
};
}

render(attributes = this.parsedAttributes, container) {
super.render(attributes, container);

this.drawPriceShape(attributes, container);
this.drawCurrencyShape(attributes, container);
this.drawPercentShape(attributes, container);
this.drawTriangleShape(attributes, container);
this.drawVariableShape(attributes, container);
this.drawProcessBarShape(attributes, container);
this.drawCollapseShape(attributes, container);

}
}

register(ExtensionCategory.NODE, 'tree-node', TreeNode);

fetch('https://assets.antv.antgroup.com/g6/decision-tree.json')
.then((res) => res.json())
.then((data) => {
const graph = new Graph({
animation:false,
container: 'container',
data: treeToGraphData(data, {
getNodeData: (datum, depth) => {
if (!datum.style) datum.style = {};
datum.style.collapsed = depth >= 2;
if (!datum.children) return datum;
const { children, ...restDatum } = datum;
return { ...restDatum, children: children.map((child) => child.id) };
},
}),
node: {
type: 'tree-node',
style: {
size: [202, 60],
ports: [{ placement: 'left' }, { placement: 'right' }],
radius: 4,
},
},
edge: {
type: 'cubic-horizontal',
style: {
stroke: GREY_COLOR,
},
},
layout: {
type: 'indented',
direction: 'LR',
dropCap: false,
indent: 300,
getHeight: () => 60,
},
behaviors: ['zoom-canvas', 'drag-canvas'],
});

graph.once(GraphEvent.AFTER_RENDER, () => {
  // graph.fitView();
});

graph.render();

});

@joshua177
Copy link
Author

上面是官方给的示例: https://g6.antv.antgroup.com/examples/scene-case/default/#fund-flow
只用设置 animation:false,
展开折叠的时候就会跳来跳去

@joshua177
Copy link
Author

graph.once(GraphEvent.AFTER_RENDER, () => {
// graph.fitView();
});
每次渲染后不想让他重新居中,只想让他保留原来的位置,如果不在视图区域可以自己拖动,比画布跳来跳去的体验要好,
我尝试使用了graph.focusElement 、 Graph.translateBy 和 Graph.translateTo 并没有得到理想的效果

@Aarebecca
Copy link
Contributor

更新到 5.0.33 版本已解决

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants