家谱:修「线又错位」(我上一版的居中写法在库里不成立)+ 框宽收成头像宽 + 去掉悬停提示
用户 2026-10-03 反馈三条。**第一条是我上一版引入的回归,先说清楚**。
一、「画线又有点错位了」—— 上一版把居中从 transform 换成 `inset:0 + margin:auto`,
这一步在**这个库里不成立**:
含块是库的 `div.card`,它在 Cartesian 模式下只有 **1.8px 宽**
(宽度由内部一个空 div 撑出来,卡片是溢出绘制的)。
`inset:0` + `margin:auto` 的"居中"依赖"容器比元素宽" —— 容器只有 1.8px 时
auto 外边距分不出任何空间,卡片直接被摆在容器左上角、整体**右移 53.1px**。
实测(1600×1000、库缩放 0.9):**每一张**卡的中心都偏在节点中心右边 53.1px
(是固定的布局偏差,不是随机抖动)→ 连线仍然画在节点上,于是全部错位。
正解:`left/top: 50%` + **半个自身尺寸的负外边距**
(`margin-left: calc(var(--kin-w) / -2)`)—— 位置完全由布局决定,
**不经过 transform**,所以库那条 `:hover { transform: … }` 也顶不掉它。
⚠️ 负外边距用 calc 与尺寸共用变量,不写死 -59/-66(迟早脱节)。
⚠️ 这条路上已经栽过两次,两种错写法都别再回去:
· `transform: translate(-50%,-50%)` → hover 时被库覆盖,卡片跳半张(53×58px);
· `inset:0 + margin:auto` → 容器 1.8px 宽,卡片整体右移 53px、连线错位。
二、「外面那个框又变宽了;宽度和头像图片一致,下面显示名字就行了」:
卡片 118 → **98px**(= 96 头像 + 左右各 1px 边框),横向 padding 归零,
头像改 `width: 100%` 占满卡片内宽 —— 于是**边框刚好贴着头像**,
框里不再有多余的横向空白;头像下面就是名字(+ 与我的称呼)。
⚠️ 98×116 与 JS 的 `setCardDim` 必须同源(库按它算间距与连线落点),
所以两边都改用常量:CSS 的 `--kin-w/--kin-h` ↔ JS 的 `KIN_W/KIN_H`。
三、「鼠标放在名字上后显示了一行字:资料、以他为中心 —— 没必要,不要显示」:
那两行是我上一版加的悬停提示(`.kin-hint`),**整个删掉**(模板 + CSS)。
验证:
· 家谱可视化检查 29 → **34** 条全过,新增五条正是这次的守卫:
⑮ 每张卡正对节点中心(改坏时实测 dx=53.1)· ⑯ 框宽 = 头像宽(≤2px)
· ⑯b 尺寸不是退化的 0(防止"一起变 0"也算过)· ⑰ 无 .kin-hint
· ⑱ 头像下面是名字。
· 反向验证:把居中改回 `inset:0 + margin:auto` → ⑮ 立刻红(dx=44.1),
还原后复绿(断言不是永远绿的)。
· 连线端点独立核对:12 个端点里 9 个落在卡片附近,另 3 个是
**夫妻之间那段连接线**(画在两卡之间,本来就该在两卡之间)。
· e2e 773/0 · 第 5 轮专项 91/0 · 几何 428/0 · 移动端 684/0 · 交互 97/0。
· 部署脚本更新/新增静态断言:允许 transform 之外的居中方式但**禁止那两种错写法**
(transform 居中 / inset:0)、必须有 `margin-left: calc(var(--kin-w) / -2)`、
JS 与 CSS 的宽度必须一致、`kin-hint` 不许回来。
· 线上两个文件 md5 与本地一致;kin-hint=0、--kin-w: 98px 在位。
This commit is contained in:
+44
-38
@@ -621,12 +621,22 @@ textarea.input { min-height: 76px; resize: vertical; }
|
|||||||
· 卡片不再整张是链接:只有 .kin-nm 是 <a>,右下角是独立的 <button>,
|
· 卡片不再整张是链接:只有 .kin-nm 是 <a>,右下角是独立的 <button>,
|
||||||
两者分开,避免"点按钮却进了成员页"的误触。
|
两者分开,避免"点按钮却进了成员页"的误触。
|
||||||
卡片尺寸与 JS 的 setCardDim({w,h}) 必须一致(库按它算间距与连线落点)。 */
|
卡片尺寸与 JS 的 setCardDim({w,h}) 必须一致(库按它算间距与连线落点)。 */
|
||||||
|
/* 卡片尺寸:**框宽 = 头像宽**(用户 2026-10-03 第 8 条:「外面那个框,宽度和头像图片一致,
|
||||||
|
下面显示名字就行了」)。
|
||||||
|
98 = 96(头像实际宽度,见 .kin-ph)+ 左右各 1px 边框 —— 即"边框刚好贴着头像",
|
||||||
|
框里不再有多余的横向空白(原来是 118 宽、比头像宽出 22px)。
|
||||||
|
⚠️ 横向 padding 必须是 0,否则头像(width:100%)会被压窄。
|
||||||
|
⚠️ 这个 98×116 必须与 JS 里 setCardDim({w,h}) **保持一致**:
|
||||||
|
库按它算卡片间距与连线落点,两边不一致连线就会歪。 */
|
||||||
.kin-card {
|
.kin-card {
|
||||||
|
--kin-w: 98px;
|
||||||
|
--kin-h: 116px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: flex; flex-direction: column; align-items: center;
|
display: flex; flex-direction: column; align-items: center;
|
||||||
gap: 0;
|
gap: 0;
|
||||||
width: 118px; height: 132px;
|
width: var(--kin-w);
|
||||||
box-sizing: border-box; padding: 6px 6px 4px;
|
height: var(--kin-h);
|
||||||
|
box-sizing: border-box; padding: 5px 0 4px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
border: 1px solid var(--line);
|
border: 1px solid var(--line);
|
||||||
@@ -637,50 +647,54 @@ textarea.input { min-height: 76px; resize: vertical; }
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
pointer-events: auto; /* 父 .card_cont 是 none,这里恢复 */
|
pointer-events: auto; /* 父 .card_cont 是 none,这里恢复 */
|
||||||
}
|
}
|
||||||
/* ⚠️⚠️ 「鼠标放上去卡片会跳」的根因就在这里(用户 2026-10-03 反馈)。
|
/* ⚠️⚠️ 居中**绝不能**用 transform、也不能用 `inset:0 + margin:auto`。
|
||||||
库自带样式里有一条:`.f3 div.card:hover > div { transform: translate(0px,-2px); }`
|
两次踩坑记录(都是用户先发现的:一次"鼠标移上去框会动",一次"线又错位了"):
|
||||||
—— 我们的 .kin-card 正好是 `div.card` 的**直接子 div**,于是鼠标一进卡片,
|
· 用 `transform: translate(-50%,-50%)`:库自带
|
||||||
这条规则就把**我们用来居中的 `transform: translate(-50%,-50%)` 整个覆盖掉**。
|
`.f3 div.card:hover > div { transform: translate(0,-2px) }` 会把居中 transform
|
||||||
实测(1600×1000 视口、库缩放 0.9):卡片从 translate(-59px,-66px) 变成
|
**整份覆盖** → 鼠标一进卡片整张卡跳 53×58px(半张卡)。
|
||||||
translate(0,-2px),整张卡**向右下跳 53.1 × 57.6 屏幕像素**(正好是半张卡)。
|
· 用 `inset: 0` + `margin: auto`:**在这里不成立** —— 含块是库的 `div.card`,
|
||||||
修法:不再用 transform 居中,改用 `inset: 0` + `margin: auto`
|
在 Cartesian 模式下它只有 **1.8px 宽**(宽度由内部一个空 div 撑出来),
|
||||||
—— 绝对定位 + inset 全 0 + margin auto 就是"在包含块里居中",
|
auto 外边距在一个比卡片还窄的盒子里根本分不出空间,结果卡片整体**右移了 53.1px**
|
||||||
完全不依赖 transform,库那条规则再怎么覆盖也影响不到位置。
|
(实测每张卡的中心都偏在节点右边 53.1px)→ 连线与卡片错位。
|
||||||
(也因此**不需要**去覆盖库的 :hover —— 少一处 !important,少一处将来的漂移。)
|
正解:`left/top: 50%` + **半个自身尺寸的负外边距** —— 位置完全由布局决定,
|
||||||
⚠️ 别改回 `left/top: 50% + transform: translate(-50%,-50%)`:那正是这次的 bug。 */
|
不经过 transform,库那条 :hover 规则怎么覆盖都影响不到。
|
||||||
|
⚠️ 负外边距必须写 `calc(var(--kin-*) / -2)`,与上面的尺寸共用同一个变量;
|
||||||
|
写成死数字(-59/-66)迟早会和尺寸脱节。 */
|
||||||
.kin-card {
|
.kin-card {
|
||||||
inset: 0;
|
left: 50%; top: 50%;
|
||||||
margin: auto;
|
margin-left: calc(var(--kin-w) / -2);
|
||||||
|
margin-top: calc(var(--kin-h) / -2);
|
||||||
}
|
}
|
||||||
/* ⚠️⚠️ 还要把库那条 `:hover` 位移**归零**(用户反馈的第二半)。
|
/* ⚠️ 还要把库那条 `:hover` 位移**归零**(用户反馈「鼠标放上去框会动」的另一半)。
|
||||||
库的 family-chart.css:517 有:
|
库的 family-chart.css:517 有:
|
||||||
`.f3 div.card:hover > div { transform: translate(0, -2px); }`
|
`.f3 div.card:hover > div { transform: translate(0, -2px); }`
|
||||||
它不只覆盖居中(那已由上面的 inset+margin auto 解决),还会给卡片加一个
|
它除了覆盖居中,还会给卡片一个纯视觉的"上浮 2px"(实测 dy = -1.8px)。
|
||||||
纯视觉的"上浮 2px"——实测 mouse 一进卡片,屏幕位置就 dy = **-1.8px**。
|
我们自绘的宣纸卡不需要库那套悬停装饰,直接归零。
|
||||||
2px 的抖动正是用户说的「那个框会移动一下」。
|
⚠️ 不去改 vendor 里那份文件(升级库会整份覆盖、改动静默消失):
|
||||||
我们的卡片是**自绘的宣纸卡**,不需要库那套"悬停上浮"装饰,所以直接归零。
|
在 app.css 覆盖即可 —— 它加载在 family-chart.css **之后**,
|
||||||
⚠️ 不能去改 vendor 里那份文件(升级库会整份覆盖,改动会静默消失),
|
同特异性下后写的赢,**不需要 !important**。 */
|
||||||
所以在 app.css 里覆盖;app.css 在 family-chart.css **之后**加载(见 kin/tree.php),
|
|
||||||
同特异性下后写的赢,不需要 !important。 */
|
|
||||||
.kin-chart.f3 div.card:hover > div { transform: none; }
|
.kin-chart.f3 div.card:hover > div { transform: none; }
|
||||||
.kin-chart.f3 div.card > div { transition: none; }
|
.kin-chart.f3 div.card > div { transition: none; }
|
||||||
.kin-card:hover {
|
.kin-card:hover {
|
||||||
box-shadow: var(--shadow-l); border-color: var(--brand-2);
|
box-shadow: var(--shadow-l); border-color: var(--brand-2);
|
||||||
}
|
}
|
||||||
/* 头像外框:**长方形**,宽度贴合头像显示宽度。
|
/* 头像外框:**占满卡片内宽**(卡片 padding 横向为 0,所以这里 100% = 卡片内宽),
|
||||||
用户 2026-10-03 第 7 条:**头像本身是链接**(点它进这个人的资料页)。
|
长方形、object-fit: contain 不裁切。
|
||||||
⚠️ 它是 <a> 不是 <span> —— 见模板里的说明("点哪儿去哪儿"用链接最自然)。 */
|
用户 2026-10-03 第 8 条:「外面那个框,宽度和头像图片一致,下面显示名字就行了」
|
||||||
|
—— 框宽 == 头像宽,头像下面只有名字。 */
|
||||||
.kin-card .kin-ph {
|
.kin-card .kin-ph {
|
||||||
width: 96px; height: 72px; border-radius: 6px; overflow: hidden;
|
width: 100%; height: 72px; border-radius: 8px 8px 0 0; overflow: hidden;
|
||||||
background: #F1E7D6; flex: 0 0 auto;
|
background: #F1E7D6; flex: 0 0 auto;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.kin-card .kin-ph img {
|
.kin-card .kin-ph img {
|
||||||
width: 100%; height: 100%; object-fit: contain; display: block;
|
width: 100%; height: 100%; object-fit: contain; display: block;
|
||||||
}
|
}
|
||||||
.kin-card .kin-ph:hover { box-shadow: 0 0 0 2px var(--brand-2); }
|
.kin-card .kin-ph:hover { box-shadow: inset 0 0 0 2px var(--brand-2); }
|
||||||
/* 姓名:用户 2026-10-03 第 7 条改为**以他为中心看家谱**的入口(原来是进资料页)。
|
/* 姓名:用户 2026-10-03 第 7 条起,点姓名 = **以他为中心**重画家谱
|
||||||
底下一行小字说明这一处能干什么 —— 不然"点名字会换一张图"没人猜得到。 */
|
(点头像才是进资料页)。
|
||||||
|
⚠️ 第 8 条明确要求**不要再显示"资料 / 以他为中心"那两行悬停提示**(没必要)——
|
||||||
|
所以 .kin-hint 这套已整个删掉,卡片上头像下面只有名字。 */
|
||||||
.kin-card .kin-nm {
|
.kin-card .kin-nm {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 12.5px; font-weight: 600; line-height: 1.25; max-width: 100%;
|
font-size: 12.5px; font-weight: 600; line-height: 1.25; max-width: 100%;
|
||||||
@@ -688,14 +702,6 @@ textarea.input { min-height: 76px; resize: vertical; }
|
|||||||
margin-top: 5px; color: var(--ink); text-decoration: none;
|
margin-top: 5px; color: var(--ink); text-decoration: none;
|
||||||
}
|
}
|
||||||
.kin-card .kin-nm:hover { color: var(--brand); text-decoration: underline; }
|
.kin-card .kin-nm:hover { color: var(--brand); text-decoration: underline; }
|
||||||
/* 两张"功能提示"用极小的字,且**只在指针悬停时**出现 ——
|
|
||||||
不悬停时不占视觉重量(卡片本来就小,常驻两行提示会把它塞满)。 */
|
|
||||||
.kin-card .kin-hint {
|
|
||||||
font-size: 9.5px; line-height: 1.2; color: var(--faint);
|
|
||||||
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
|
|
||||||
max-width: 100%; opacity: 0; transition: opacity .15s ease;
|
|
||||||
}
|
|
||||||
.kin-card:hover .kin-hint { opacity: 1; }
|
|
||||||
/* 称呼在姓名下面一行,用品牌色的浅字(参考实现是「(称呼)」) */
|
/* 称呼在姓名下面一行,用品牌色的浅字(参考实现是「(称呼)」) */
|
||||||
.kin-card .kin-lb {
|
.kin-card .kin-lb {
|
||||||
font-size: 10.5px; color: var(--brand); line-height: 1.2; max-width: 100%;
|
font-size: 10.5px; color: var(--brand); line-height: 1.2; max-width: 100%;
|
||||||
|
|||||||
@@ -212,9 +212,15 @@ $datumJson = json_encode(
|
|||||||
.setCardXSpacing(160)
|
.setCardXSpacing(160)
|
||||||
.setCardYSpacing(180);
|
.setCardYSpacing(180);
|
||||||
|
|
||||||
|
/* ⚠️ 卡片尺寸**必须与 CSS 里 .kin-card 的 --kin-w/--kin-h 一致**:
|
||||||
|
库按这个尺寸算卡片间距与连线落点,两边一旦不一致,连线就会与卡片错位
|
||||||
|
(用户 2026-10-03 反馈过一次"线又错位了",就是尺寸/居中改动引起的)。
|
||||||
|
98 = 96(头像宽)+ 左右各 1px 边框;见 app.css 的 .kin-card。 */
|
||||||
|
var KIN_W = 98, KIN_H = 116;
|
||||||
|
|
||||||
chart.setCardHtml()
|
chart.setCardHtml()
|
||||||
.setStyle('rect')
|
.setStyle('rect')
|
||||||
.setCardDim({ w: 118, h: 132, mini_tree: false })
|
.setCardDim({ w: KIN_W, h: KIN_H, mini_tree: false })
|
||||||
.setCardInnerHtmlCreator(function (d) {
|
.setCardInnerHtmlCreator(function (d) {
|
||||||
var p = (d.data && d.data.data) || {};
|
var p = (d.data && d.data.data) || {};
|
||||||
var id = (d.data && d.data.id) || '';
|
var id = (d.data && d.data.id) || '';
|
||||||
@@ -243,10 +249,8 @@ $datumJson = json_encode(
|
|||||||
+ esc(p.name) + '</a>'
|
+ esc(p.name) + '</a>'
|
||||||
+ '<span class="kin-lb">' + esc(p.label) + '</span>'
|
+ '<span class="kin-lb">' + esc(p.label) + '</span>'
|
||||||
+ (p.ph ? '<span class="kin-mark">待确认</span>' : '')
|
+ (p.ph ? '<span class="kin-mark">待确认</span>' : '')
|
||||||
// 两张提示分挂到头像/姓名下面,**悬停时才显形**(见 CSS 的 .kin-hint):
|
// ⚠️ 用户 2026-10-03 第 8 条:**不要再放「资料 / 以他为中心」那两行悬停提示**
|
||||||
// 这样"点哪儿去哪儿"一眼可辨,不悬停时又不占地方。
|
// (原话「没必要,不要显示这个提示了」)。头像下面是名字,就够了。
|
||||||
+ '<span class="kin-hint kin-hint-ph">资料</span>'
|
|
||||||
+ '<span class="kin-hint kin-hint-nm">以他为中心</span>'
|
|
||||||
+ '</div>';
|
+ '</div>';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user