SHA256
Связи (pixel-aquarium, 10.06): партия 2 (UI-фишки) — поиск, хлебные крошки, бейджи, цветовые кластеры
Всё в лаборатории (вариант 2: реальный путь /network-view не трогаем). - Поиск + телепорт: строка .fg-search; Enter → graph.findNode(имя) → камера летит к узлу (dive в «Вселенной», иначе перецентр). - Хлебные крошки: .fg-breadcrumb «Иван › Нина › Ада» (движок шлёт onDiveChange(path), API getDivePath); клик по корню — полный сброс, по предку — навигация на его уровень. - Бейдж числа связей: .fg-node-badge (degreeById → updateBadges; у центра — число связей 1-го уровня). - Цветовые кластеры: мягкая аура узла по типу связи (CSS is-family/friend/business/contact). Автопроверки расширены до 17 ассертов (добавлены поиск/крошки/бейдж) — прогон 17/17 PASS. Фикс: TDZ breadcrumbEl (объявлен до createForceGraph, т.к. onDiveChange вызывается при монтировании). Бамп client.version → 1.2.149. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -143,7 +143,7 @@ function hash01(str) {
|
||||
* @param {Function} [opts.onNodeLongPress] - долгое нажатие (node, screenPoint) => void
|
||||
* @returns {{ destroy: Function, recenter: Function, setModel: Function, getFocusNode: Function }}
|
||||
*/
|
||||
export function createForceGraph({ stage, model, onCenterTap, onNodeTap, onNodeLongPress, onNodeHover } = {}) {
|
||||
export function createForceGraph({ stage, model, onCenterTap, onNodeTap, onNodeLongPress, onNodeHover, onDiveChange } = {}) {
|
||||
// Слои DOM
|
||||
const edgesSvg = document.createElementNS(SVGNS, 'svg');
|
||||
edgesSvg.setAttribute('class', 'fg-edges');
|
||||
@@ -173,18 +173,25 @@ export function createForceGraph({ stage, model, onCenterTap, onNodeTap, onNodeL
|
||||
let diveZoom = 1; // целевой зум активного погружения
|
||||
let surfacing = false; // идёт «всплытие» назад (камера/зум возвращаются к корню)
|
||||
let childCountByParent = new Map(); // parentId → число детей (для адаптивного радиуса орбиты, без слипания)
|
||||
let degreeById = new Map(); // id → число связей узла (для бейджа-счётчика на аватарке)
|
||||
const rebuildIndex = () => {
|
||||
nodeById = new Map(nodes.map((n) => [String(n.id), n]));
|
||||
hasDeep = nodes.some((n) => n.tier >= 2);
|
||||
// число детей у родителя + порядковый индекс ребёнка среди братьев (для веера «полукругом наружу»)
|
||||
childCountByParent = new Map();
|
||||
degreeById = new Map();
|
||||
let tier1count = 0;
|
||||
for (const n of nodes) {
|
||||
if (n.tier >= 2 && n.parentId) {
|
||||
const i = childCountByParent.get(n.parentId) || 0;
|
||||
n.sibIndex = i;
|
||||
childCountByParent.set(n.parentId, i + 1);
|
||||
degreeById.set(n.parentId, (degreeById.get(n.parentId) || 0) + 1); // у родителя +1 связь
|
||||
} else if (n.tier === 1 && String(n.id) !== focusId) {
|
||||
tier1count += 1;
|
||||
}
|
||||
}
|
||||
degreeById.set(focusId, tier1count); // у центра — число связей 1-го уровня
|
||||
};
|
||||
|
||||
// Spotlight: при закреплённой кликом ветке остальной граф тускнеет до SPOTLIGHT_DIM (0.25), чтобы
|
||||
@@ -212,12 +219,34 @@ export function createForceGraph({ stage, model, onCenterTap, onNodeTap, onNodeL
|
||||
return set;
|
||||
}
|
||||
let _pathSet = new Set();
|
||||
let _pathSetKey = ' | ||||