Explorar el Código

优化关系树形图

Hai Lin hace 4 días
padre
commit
0cc285a9a1
Se han modificado 1 ficheros con 17 adiciones y 19 borrados
  1. 17 19
      templates/tree.html

+ 17 - 19
templates/tree.html

@@ -294,24 +294,23 @@
         let rootNode = d3.hierarchy(treeData, d => (d && d.children) || []);
         
         // 动态调整间距,保证节点绝对不重叠,长辈/同辈/配偶使用固定基础间距
-        const nodeWidth = 90; // 基础宽度
+        const nodeWidth = 120; // 增加基础宽度以避免重叠
         const nodeHeight = 260; // 基础高度,调大以避免上下层重叠
         const treemap = d3.tree().nodeSize([nodeWidth, nodeHeight]).separation((a, b) => {
-            return a.parent === b.parent ? 1.4 : 2.0;
+            return a.parent === b.parent ? 2.0 : 2.0; // 增加同级节点间距
         });
         
         let nodesHier = treemap(rootNode);
 
-        // 配偶固定在“下层半级”:纵向放到两代中间;横向围绕本人轻度展开
-        const spouseHalfLevelOffsetY = Math.round(nodeHeight * 0.5); // 半级
-        const spouseSpreadX = 110; // 多配偶时的横向间距
+        // 配偶固定在同一水平线上:与本人并列显示
+        const spouseSpreadX = 140; // 增加间距以确保不重叠
         nodesHier.descendants().forEach(parent => {
             const spouses = (parent.children || []).filter(c => c.data && c.data.isSpouseNode);
             if (spouses.length === 0) return;
             spouses.forEach((spouse, idx) => {
-                const order = idx - (spouses.length - 1) / 2;
-                spouse.x = parent.x + order * spouseSpreadX;
-                spouse.y = parent.y + spouseHalfLevelOffsetY;
+                // 计算配偶位置,从右侧开始排列
+                spouse.x = parent.x + (idx + 1) * spouseSpreadX;
+                spouse.y = parent.y; // 同一水平线
             });
         });
 
@@ -371,21 +370,20 @@
             const spouses = (node.children || []).filter(c => c.data && c.data.isSpouseNode);
 
             // 配偶连线拐点:位于本人与配偶节点之间,匹配“下层半级”显示
-            const hY = node.y + Math.round(spouseHalfLevelOffsetY * 0.55);
+            // const hY = node.y + Math.round(spouseHalfLevelOffsetY * 0.55);
             const num = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : 0);
 
-            // 夫妻关系:倒U型连线(主节点向下,然后横向连到配偶上面
+            // 夫妻关系:水平连线(主节点右侧连接到配偶左侧
             if (spouses.length > 0) {
                 const g = svg.append("g").attr("class", "link-group");
                 spouses.forEach((spouse, idx) => {
-                    // 主节点向下,拐向配偶,再向下连接配偶顶部 (spouse.y - circleR)
-                    const pathD = `M${num(node.x)},${num(node.y + circleR)} 
-                                   L${num(node.x)},${num(hY)} 
-                                   L${num(spouse.x)},${num(hY)} 
-                                   L${num(spouse.x)},${num(spouse.y - circleR)}`;
+                    // 水平连线,稍微向下偏移一点以避开节点
+                    const linkY = node.y + 10;
+                    const pathD = `M${num(node.x + circleR)},${num(linkY)} 
+                                   L${num(spouse.x - circleR)},${num(linkY)}`;
                     g.append("path").attr("class", "link link-spouse").attr("d", pathD);
                     
-                    if (idx === 0) addBadge(g, (node.x + spouse.x) / 2, hY + 14, "配偶");
+                    if (idx === 0) addBadge(g, (node.x + spouse.x) / 2, linkY, "配偶");
                 });
             }
 
@@ -395,9 +393,9 @@
             const minChildX = d3.min(realChildren, c => c.x);
             const maxChildX = d3.max(realChildren, c => c.x);
             
-            // 如果有配偶,子代主线从配偶连线的中间引出,否则从自己直接引出
-            const startX = spouses.length > 0 ? (node.x + spouses[0].x) / 2 : node.x;
-            const startY = spouses.length > 0 ? hY : node.y + circleR;
+            // 如果有配偶,子代主线从本人和最右侧配偶的中间引出,否则从自己直接引出
+            const startX = spouses.length > 0 ? (node.x + spouses[spouses.length - 1].x) / 2 : node.x;
+            const startY = node.y + circleR;
             
             // 将子女横线也相应地下移一些,避免和配偶长名字重叠
             const sibsY = childrenY - 60;