完成布局的分组优化

This commit is contained in:
锦恢 2024-12-25 22:20:04 +08:00
parent 2f1d16c303
commit 5a7dd7f6f0
5 changed files with 94 additions and 50 deletions

View File

@ -43,4 +43,8 @@ onMounted(async () => {
cursor: grabbing;
}
.port-caption {
user-select: none;
}
</style>

View File

@ -38,7 +38,7 @@ export class CellRender {
const data = this.data;
const rootRender = this.rootRender;
let cellSelections = this.parentSelection.selectAll('g')
let cellSelections = this.parentSelection.selectAll('svg')
.data(data)
.enter()
.append(data => {
@ -60,7 +60,6 @@ export class CellRender {
.on('end', function (data) {
const cellSelection = d3.select(this);
registerDragEvent(cellSelection, data, rootRender);
});
} else {
@ -69,9 +68,6 @@ export class CellRender {
.each(function (data) {
const cellSelection = d3.select(this);
// 计算最小拓扑图
const mintoGraph = undefined;
registerDragEvent(cellSelection, data, rootRender);
});
}

View File

@ -23,10 +23,6 @@ export class NetlistRender {
*/
this.elkGraph = {
id: 'root',
layoutOptions: {
'elk.progressBar': true,
'layered.nodePlacement.strategy': 'SIDE_BASED'
},
children: [],
edges: []
};
@ -80,6 +76,13 @@ export class NetlistRender {
const cellNodes = module.makeCellsElkNodes();
const [constantNodes, connectionEdges] = module.makeConnectionElkNodes();
// debug
for (const node of portNodes) {
if (node.type === 'output') {
node.x = 400;
}
}
// 挂载到渲染图中
this.elkGraph.children.push(...portNodes);
this.elkGraph.children.push(...cellNodes);
@ -97,13 +100,15 @@ export class NetlistRender {
*/
async createLayout() {
const graph = this.elkGraph;
const start = performance.now();
const layoutGraph = await this.elk.layout(graph, {
layoutOptions: {
// org.eclipse. 可以去除
'org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers': 35,
'org.eclipse.elk.spacing.nodeNode': 35,
'org.eclipse.elk.layered.layering.strategy': 'LONGEST_PATH'
'elk.spacing.nodeNode': 35,
'elk.layered.layering.strategy': 'NETWORK_SIMPLEX',
'elk.algorithm': 'layered',
'elk.partitioning.activate': true
}
});
const timecost = (performance.now() - start).toFixed(3);
@ -346,4 +351,11 @@ export class NetlistRender {
// }
}
/**
* @description 初次渲染完成后布局不一定正确需要进行调整output ports
*/
adjustLayoyt() {
}
}

View File

@ -65,21 +65,36 @@ export class Module {
for (const name of this.moduleTree.nameToPort.keys()) {
const port = this.moduleTree.nameToPort.get(name);
const direction = port.direction === 'input' ? 'LEFT': 'RIGHT';
const node = {
id: port.id,
renderName: name,
renderType: 'port',
type: port.direction,
width: LAYOUT_CONSTANT.PORT_WIDTH,
height: LAYOUT_CONSTANT.PORT_HEIGHT,
layoutOptions: {
'elk.side': direction
}
};
if (port.direction === 'input') {
const node = {
id: port.id,
renderName: name,
renderType: 'port',
type: port.direction,
width: LAYOUT_CONSTANT.PORT_WIDTH,
height: LAYOUT_CONSTANT.PORT_HEIGHT,
layoutOptions: {
'partitioning.partition': 1
}
};
nodes.push(node);
} else {
const node = {
id: port.id,
renderName: name,
renderType: 'port',
type: port.direction,
width: LAYOUT_CONSTANT.PORT_WIDTH,
height: LAYOUT_CONSTANT.PORT_HEIGHT,
layoutOptions: {
'partitioning.partition': 999
}
};
nodes.push(node);
}
nodes.push(node);
}
// 非 port 的其他内部变量的节点不需要绘制,因为它们总能被表示为中间变量
@ -165,7 +180,8 @@ export class Module {
height,
ports,
layoutOptions: {
'org.eclipse.elk.portConstraints': 'FIXED_POS'
'org.eclipse.elk.portConstraints': 'FIXED_POS',
'partitioning.partition': 10
}
};
nodes.push(node);
@ -197,10 +213,11 @@ export class Module {
width,
height,
ports,
// layoutOptions: {
// // 强制固定 port 的方向
// 'org.eclipse.elk.portConstraints': 'FIXED_SIDE'
// }
layoutOptions: {
// 强制固定 port 的方向
'org.eclipse.elk.portConstraints': 'FIXED_SIDE',
'partitioning.partition': 10
}
};
nodes.push(node);
@ -240,7 +257,8 @@ export class Module {
width: LAYOUT_CONSTANT.CONSTANT_WIDTH,
height: LAYOUT_CONSTANT.CONSTANT_HEIGHT,
layoutOptions: {
'elk.port.side': 'WEST'
'elk.port.side': 'WEST',
'partitioning.partition': 10
}
};

View File

@ -35,42 +35,53 @@ export class PortRender {
render() {
const data = this.data;
let portSelections = this.parentSelection.selectAll('rect')
let portSelections = this.parentSelection.selectAll('g.port')
.data(data)
.enter()
.append('rect')
.attr('x', data => data.x)
.attr('y', data => data.y)
.append('g')
.attr('class', 'port')
.attr("transform", d => `translate(${d.x}, ${d.y})`);
let ports = portSelections.append('rect')
.attr('width', data => data.width)
.attr('height', data => data.height)
.attr('fill', d => d.fill);
let texts = portSelections.append('text')
.attr('x', data => data.width / 2) // 文本的 x 坐标(居中)
.attr('y', data => data.height / 2) // 文本的 y 坐标(居中)
.attr('dominant-baseline', 'middle') // 文本垂直居中
.attr('text-anchor', 'middle') // 文本水平居中
.attr('fill', 'white') // 文本颜色
.attr('font-size', '0')
.transition()
.duration(1000)
.attr('font-size', '12px')
.attr('class', 'port-caption')
.text(data => data.text); // 设置文本内容
portSelections.append("text")
.attr("x", d => d.width / 2)
.attr("y", d => d.height / 2)
.text(d => d.text)
.attr('font-size', '12px');
if (globalSetting.renderAnimation) {
portSelections = portSelections
.transition()
ports.transition()
.duration(1000)
.attr('stroke', 'var(--main-color)')
.attr('stroke-width', 2)
.attr('rx', d => d.rx)
.attr('ry', d => d.ry)
.attr('ry', d => d.ry);
portSelections
.attr('class', 'grab')
.on('end', function (data) {
.each(function (data) {
const portSelection = d3.select(this);
registerDragEvent(portSelection, data);
});
} else {
portSelections
.attr('stroke', 'var(--main-color)')
ports.attr('stroke', 'var(--main-color)')
.attr('stroke-width', 2)
.attr('rx', d => d.rx)
.attr('ry', d => d.ry)
.attr('ry', d => d.ry);
portSelections
.attr('class', 'grab')
.each(function (data) {
const portSelection = d3.select(this);
@ -84,6 +95,9 @@ export class PortRender {
}
}
/**
* @description 注册关于 器件 的拖动事件
*
@ -116,10 +130,10 @@ function dragStart(event, selection, data) {
* @param {d3.D3DragEvent} event
* @param {d3.Selection} selection
*/
function dragged(event, selection, data) {
function dragged(event, selection, data) {
data.x = event.x;
data.y = event.y;
selection.attr('x', event.x).attr('y', event.y);
selection.attr("transform", `translate(${event.x}, ${event.y})`);
}
/**