圆圈不重叠了
This commit is contained in:
parent
b00b1293e4
commit
1688d8b200
|
|
@ -8,6 +8,38 @@
|
||||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||||
import G6 from "@antv/g6";
|
import G6 from "@antv/g6";
|
||||||
|
|
||||||
|
// 注册自定义边
|
||||||
|
G6.registerEdge('combo-border-edge', {
|
||||||
|
draw(cfg, group) {
|
||||||
|
const { sourceCombo, targetCombo } = cfg;
|
||||||
|
if (!sourceCombo || !targetCombo) return;
|
||||||
|
// 获取圆心和半径
|
||||||
|
const { x: x1, y: y1, r: r1 } = sourceCombo;
|
||||||
|
const { x: x2, y: y2, r: r2 } = targetCombo;
|
||||||
|
// 计算两个圆心连线的单位向量
|
||||||
|
const dx = x2 - x1, dy = y2 - y1;
|
||||||
|
const len = Math.sqrt(dx * dx + dy * dy);
|
||||||
|
const ux = dx / len, uy = dy / len;
|
||||||
|
// 计算切点
|
||||||
|
const sx = x1 + ux * r1;
|
||||||
|
const sy = y1 + uy * r1;
|
||||||
|
const tx = x2 - ux * r2;
|
||||||
|
const ty = y2 - uy * r2;
|
||||||
|
// 绘制曲线或直线
|
||||||
|
return group.addShape('path', {
|
||||||
|
attrs: {
|
||||||
|
stroke: '#fff',
|
||||||
|
lineWidth: 2,
|
||||||
|
path: [
|
||||||
|
['M', sx, sy],
|
||||||
|
// 可加弯曲 ['Q', (sx+tx)/2+20, (sy+ty)/2-20, tx, ty]
|
||||||
|
['L', tx, ty]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 'line');
|
||||||
|
|
||||||
let graph = null;
|
let graph = null;
|
||||||
const containerRef = ref(null);
|
const containerRef = ref(null);
|
||||||
|
|
||||||
|
|
@ -87,28 +119,74 @@ onMounted(() => {
|
||||||
|
|
||||||
// --- 2. G6 Graph Initialization ---
|
// --- 2. G6 Graph Initialization ---
|
||||||
const container = containerRef.value;
|
const container = containerRef.value;
|
||||||
|
// 1. 统计每个combo的节点数量
|
||||||
|
const comboNodeCount = {};
|
||||||
|
nodes.forEach(node => {
|
||||||
|
comboNodeCount[node.comboId] = (comboNodeCount[node.comboId] || 0) + 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 先排序
|
||||||
|
const sortedCombos = combos
|
||||||
|
.map(combo => ({ ...combo, count: comboNodeCount[combo.id] || 0 }))
|
||||||
|
.sort((a, b) => b.count - a.count);
|
||||||
|
|
||||||
|
// 计算每排最大半径
|
||||||
|
const topCombos = sortedCombos.slice(0, 3);
|
||||||
|
const bottomCombos = sortedCombos.slice(3, 6);
|
||||||
|
const topMaxR = Math.max(...topCombos.map(c => c.r));
|
||||||
|
const bottomMaxR = Math.max(...bottomCombos.map(c => c.r));
|
||||||
|
|
||||||
|
// 横向间距 = 前后两个combo半径之和 + 额外间隔
|
||||||
|
function getX(i, combosArr, width) {
|
||||||
|
let x = combosArr[0].r + 60; // 左边留空
|
||||||
|
for (let j = 0; j < i; j++) {
|
||||||
|
x += combosArr[j].r + combosArr[j + 1].r + 80; // 80为额外间隔
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
const width = container.scrollWidth || 1200;
|
const width = container.scrollWidth || 1200;
|
||||||
const height = container.scrollHeight || 800;
|
const height = container.scrollHeight || 800;
|
||||||
|
const topY = height * 0.25;
|
||||||
|
const bottomY = height * 0.75;
|
||||||
|
|
||||||
|
// 上排
|
||||||
|
topCombos.forEach((combo, idx) => {
|
||||||
|
combo.x = getX(idx, topCombos, width);
|
||||||
|
combo.y = topY;
|
||||||
|
});
|
||||||
|
// 下排
|
||||||
|
bottomCombos.forEach((combo, idx) => {
|
||||||
|
combo.x = getX(idx, bottomCombos, width);
|
||||||
|
combo.y = bottomY;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新 combos
|
||||||
|
combos.forEach(c => {
|
||||||
|
const found = [...topCombos, ...bottomCombos].find(sc => sc.id === c.id);
|
||||||
|
c.x = found.x;
|
||||||
|
c.y = found.y;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 5. 节点分布在各自combo圆内
|
||||||
|
nodes.forEach(node => {
|
||||||
|
const combo = combos.find(c => c.id === node.comboId);
|
||||||
|
// 随机分布在combo圆内
|
||||||
|
const angle = Math.random() * 2 * Math.PI;
|
||||||
|
const radius = Math.random() * (combo.r - nodeSize / 2);
|
||||||
|
node.x = combo.x + Math.cos(angle) * radius;
|
||||||
|
node.y = combo.y + Math.sin(angle) * radius;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 6. 用 layout: null,G6 不再自动布局
|
||||||
graph = new G6.Graph({
|
graph = new G6.Graph({
|
||||||
container,
|
container,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
layout: null, // 或你自定义的布局
|
groupByTypes: false,
|
||||||
groupByTypes: false, // 允许 combo-to-combo 边
|
layout: null,
|
||||||
// --- MODIFICATION: Set preventComboOverlap to true to avoid circle overlaps ---
|
|
||||||
layout: {
|
|
||||||
type: 'comboForce',
|
|
||||||
preventComboOverlap: true, // 让combo不重叠
|
|
||||||
preventNodeOverlap: true, // 节点不重叠
|
|
||||||
linkDistance: 250, // 连接距离
|
|
||||||
nodeSpacing: 50, // 节点间距
|
|
||||||
comboSpacing: 150, // combo间距(可根据实际效果调整,数值越大圆圈越分开)
|
|
||||||
gravity: 40,
|
|
||||||
comboGravity: 30,
|
|
||||||
},
|
|
||||||
modes: {
|
modes: {
|
||||||
default: ['drag-canvas', 'zoom-canvas', 'drag-combo', 'drag-node'],
|
default: ['drag-canvas', 'zoom-canvas', 'drag-combo', 'drag-node']
|
||||||
},
|
},
|
||||||
defaultNode: {
|
defaultNode: {
|
||||||
size: nodeSize,
|
size: nodeSize,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user