SHA256
Связи: интерактивная карта связей (force-directed graph)
Переработка экрана «Связи» в интерактивный нод-граф с премиальными переходами. Движок (js/pages/network/force-graph.js): - diffing-переходы: общие узлы перелетают, новые расцветают каскадом, исчезнувшие — Ghost-слой (800мс, на месте); - мягкая радиальная пружина + отталкивание (органичная орбита), упругий влёт фокуса; - динамическая вязкость на старте (трение 0.92→0.82, отталкивание ослаблено) — мягкий разлёт без тряски; - жёсткая заморозка (kill-switch) при затухании — нет «треска», экономия батареи; - линии — SVG <path> Безье (изогнутые нити), прорастание; жесты pan с инерцией; - хард-лимит DOM-аватарок (остальное — SVG-точки). Интеграция и UX: - adapter.js: getUserConnectionsGraph → модель движка (сервер не трогаем, read-only); - фильтры (Все/Семья/Друзья/Сияющие), контекстное меню (node-menu.js), нижний сниппет, профиль; - прицел в центре, дыхание фокуса, свечение сияющих; - лаборатория network-view/lab на мок-данных (networkGraphUsers) для тестов без бэкенда. Документация: shine-UI/Dev_Docs/features/interactive-network-graph.md. Бамп client.version 1.2.135 -> 1.2.136. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -280,3 +280,116 @@ export const networkGraph = {
|
||||
{ id: 'p4', name: 'Никита', initials: 'НО', x: 82, y: 76 },
|
||||
],
|
||||
};
|
||||
|
||||
// Мок интерактивной карты связей в форме ТЗ (focusUser + connections[]).
|
||||
// Используется лабораторным режимом `network-view/lab` для проверки физики/центрирования.
|
||||
// relationType: family | friend | business | contact; connectionStrength: 0..1 (сильнее → ближе к центру);
|
||||
// status: 'shining' даёт эффект свечения; hasOwnConnections — есть ли у узла свои связи (для глубины).
|
||||
export const networkGraphMock = {
|
||||
focusUser: { id: 'u_100', login: 'ivan', name: 'Иван', avatar: 'url_to_image', status: 'shining' },
|
||||
connections: [
|
||||
{ id: 'u_101', login: 'alisa', name: 'Алиса', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.95, hasOwnConnections: true, status: 'shining' },
|
||||
{ id: 'u_102', login: 'pavel', name: 'Павел', avatar: 'url_to_image', relationType: 'business', connectionStrength: 0.45, hasOwnConnections: false },
|
||||
{ id: 'u_103', login: 'marina', name: 'Марина', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.8, hasOwnConnections: true },
|
||||
{ id: 'u_104', login: 'ilya', name: 'Илья', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.6, hasOwnConnections: true },
|
||||
{ id: 'u_105', login: 'elena', name: 'Елена', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.88, hasOwnConnections: false },
|
||||
{ id: 'u_106', login: 'nikita', name: 'Никита', avatar: 'url_to_image', relationType: 'contact', connectionStrength: 0.3, hasOwnConnections: false },
|
||||
{ id: 'u_107', login: 'oleg', name: 'Олег', avatar: 'url_to_image', relationType: 'business', connectionStrength: 0.55, hasOwnConnections: true, status: 'shining' },
|
||||
{ id: 'u_108', login: 'sveta', name: 'Света', avatar: 'url_to_image', relationType: 'friend', connectionStrength: 0.7, hasOwnConnections: false },
|
||||
{ id: 'u_109', login: 'dmitry', name: 'Дмитрий', avatar: 'url_to_image', relationType: 'contact', connectionStrength: 0.4, hasOwnConnections: true },
|
||||
{ id: 'u_110', login: 'anna', name: 'Анна', avatar: 'url_to_image', relationType: 'family', connectionStrength: 0.92, hasOwnConnections: false },
|
||||
],
|
||||
};
|
||||
|
||||
// Связанный мульти-пользовательский граф для лаборатории (network-view/lab):
|
||||
// у каждого пользователя свой набор связей, тап по узлу переключает карту на его сеть.
|
||||
// Сияющими считаем ivan/alisa/oleg — у них статус подсвечивается и в их карточках у других.
|
||||
const NETWORK_NAMES = {
|
||||
ivan: 'Иван', alisa: 'Алиса', pavel: 'Павел', elena: 'Елена', dmitry: 'Дмитрий',
|
||||
oleg: 'Олег', nina: 'Нина', marina: 'Марина', sveta: 'Света', kirill: 'Кирилл',
|
||||
};
|
||||
const NETWORK_SHINING = new Set(['ivan', 'alisa', 'oleg']);
|
||||
|
||||
function networkConn(login, relationType, connectionStrength) {
|
||||
return {
|
||||
id: login,
|
||||
login,
|
||||
name: NETWORK_NAMES[login] || login,
|
||||
avatar: null,
|
||||
relationType,
|
||||
connectionStrength,
|
||||
hasOwnConnections: true,
|
||||
status: NETWORK_SHINING.has(login) ? 'shining' : '',
|
||||
};
|
||||
}
|
||||
|
||||
function networkPerson(login, connections) {
|
||||
return {
|
||||
focusUser: {
|
||||
id: login,
|
||||
login,
|
||||
name: NETWORK_NAMES[login] || login,
|
||||
avatar: null,
|
||||
status: NETWORK_SHINING.has(login) ? 'shining' : '',
|
||||
},
|
||||
connections,
|
||||
};
|
||||
}
|
||||
|
||||
export const networkGraphUsers = {
|
||||
ivan: networkPerson('ivan', [
|
||||
networkConn('alisa', 'friend', 0.9),
|
||||
networkConn('pavel', 'friend', 0.7),
|
||||
networkConn('elena', 'family', 0.95),
|
||||
networkConn('dmitry', 'family', 0.95),
|
||||
networkConn('oleg', 'business', 0.5),
|
||||
networkConn('nina', 'contact', 0.35),
|
||||
networkConn('kirill', 'friend', 0.6),
|
||||
]),
|
||||
alisa: networkPerson('alisa', [
|
||||
networkConn('ivan', 'friend', 0.9),
|
||||
networkConn('marina', 'friend', 0.8),
|
||||
networkConn('sveta', 'contact', 0.4),
|
||||
networkConn('elena', 'contact', 0.3),
|
||||
]),
|
||||
pavel: networkPerson('pavel', [
|
||||
networkConn('ivan', 'friend', 0.7),
|
||||
networkConn('oleg', 'business', 0.6),
|
||||
networkConn('kirill', 'friend', 0.5),
|
||||
]),
|
||||
elena: networkPerson('elena', [
|
||||
networkConn('ivan', 'family', 0.95),
|
||||
networkConn('dmitry', 'family', 0.9),
|
||||
networkConn('alisa', 'contact', 0.3),
|
||||
]),
|
||||
dmitry: networkPerson('dmitry', [
|
||||
networkConn('ivan', 'family', 0.95),
|
||||
networkConn('elena', 'family', 0.9),
|
||||
networkConn('pavel', 'business', 0.4),
|
||||
]),
|
||||
oleg: networkPerson('oleg', [
|
||||
networkConn('pavel', 'business', 0.6),
|
||||
networkConn('ivan', 'business', 0.5),
|
||||
networkConn('nina', 'contact', 0.45),
|
||||
]),
|
||||
nina: networkPerson('nina', [
|
||||
networkConn('ivan', 'contact', 0.35),
|
||||
networkConn('oleg', 'contact', 0.45),
|
||||
networkConn('sveta', 'friend', 0.5),
|
||||
]),
|
||||
marina: networkPerson('marina', [
|
||||
networkConn('alisa', 'friend', 0.8),
|
||||
networkConn('sveta', 'friend', 0.7),
|
||||
networkConn('kirill', 'contact', 0.4),
|
||||
]),
|
||||
sveta: networkPerson('sveta', [
|
||||
networkConn('marina', 'friend', 0.7),
|
||||
networkConn('alisa', 'contact', 0.4),
|
||||
networkConn('nina', 'friend', 0.5),
|
||||
]),
|
||||
kirill: networkPerson('kirill', [
|
||||
networkConn('ivan', 'friend', 0.6),
|
||||
networkConn('pavel', 'friend', 0.5),
|
||||
networkConn('marina', 'contact', 0.4),
|
||||
]),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user