chore: 修改渲染设置
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
import { useEffect, useRef } from 'react';
|
import { useEffect, useRef, useMemo } from 'react';
|
||||||
import { Graph } from '@antv/g6';
|
import { Graph } from '@antv/g6';
|
||||||
import type { GraphData, Node, Edge, GraphLayoutConfig } from '../../types/graph';
|
import type { GraphData, Node, Edge, GraphLayoutConfig } from '../../types/graph';
|
||||||
import { getNodeColors } from '../../config/colors';
|
import { getNodeColors } from '../../config/colors';
|
||||||
import { FORCE_LAYOUT_CONFIG, GRAPH_BEHAVIORS } from '../../config/layout';
|
import { FORCE_LAYOUT_CONFIG, GRAPH_BEHAVIORS } from '../../config/layout';
|
||||||
import { GRAPH_DEFAULT_HEIGHT } from '../../config/constants';
|
import { GRAPH_DEFAULT_HEIGHT } from '../../config/constants';
|
||||||
|
import { getNodeStyle, getEdgeStyle } from '../../utils/graphStyle';
|
||||||
|
|
||||||
interface GraphViewProps {
|
interface GraphViewProps {
|
||||||
data: GraphData;
|
data: GraphData;
|
||||||
@@ -30,6 +31,8 @@ export const GraphView = ({
|
|||||||
|
|
||||||
const onNodeClickRef = useRef(onNodeClick);
|
const onNodeClickRef = useRef(onNodeClick);
|
||||||
|
|
||||||
|
const nodeMap = useMemo(() => new Map(data.nodes.map((node: Node) => [node.id, node])), [data.nodes]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onNodeClickRef.current = onNodeClick;
|
onNodeClickRef.current = onNodeClick;
|
||||||
}, [onNodeClick]);
|
}, [onNodeClick]);
|
||||||
@@ -69,26 +72,27 @@ export const GraphView = ({
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
edges: data.edges.map((edge: Edge) => ({
|
edges: data.edges.map((edge: Edge) => {
|
||||||
id: edge.id,
|
return {
|
||||||
source: edge.source,
|
id: edge.id,
|
||||||
target: edge.target,
|
|
||||||
label: edge.label,
|
|
||||||
data: {
|
|
||||||
source: edge.source,
|
source: edge.source,
|
||||||
target: edge.target,
|
target: edge.target,
|
||||||
label: edge.label,
|
label: edge.label,
|
||||||
type: edge.type,
|
data: {
|
||||||
properties: edge.properties,
|
source: edge.source,
|
||||||
},
|
target: edge.target,
|
||||||
style: {
|
label: edge.label,
|
||||||
stroke: '#95A5A6',
|
type: edge.type,
|
||||||
lineWidth: 2,
|
properties: edge.properties,
|
||||||
labelText: edge.label,
|
},
|
||||||
labelFill: '#666',
|
style: {
|
||||||
labelFontSize: 10,
|
stroke: '#95A5A6',
|
||||||
},
|
labelText: edge.label,
|
||||||
})),
|
labelFill: '#666',
|
||||||
|
labelFontSize: 10,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建图谱配置
|
// 创建图谱配置
|
||||||
@@ -101,8 +105,8 @@ export const GraphView = ({
|
|||||||
node: {
|
node: {
|
||||||
type: 'circle',
|
type: 'circle',
|
||||||
style: {
|
style: {
|
||||||
size: 50,
|
|
||||||
lineWidth: 2,
|
lineWidth: 2,
|
||||||
|
...getNodeStyle(),
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
selected: {
|
selected: {
|
||||||
@@ -117,13 +121,12 @@ export const GraphView = ({
|
|||||||
edge: {
|
edge: {
|
||||||
type: 'line',
|
type: 'line',
|
||||||
style: {
|
style: {
|
||||||
lineWidth: 1,
|
|
||||||
endArrow: true,
|
endArrow: true,
|
||||||
|
...getEdgeStyle(nodeMap),
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
selected: {
|
selected: {
|
||||||
stroke: '#1890FF',
|
stroke: '#1890FF',
|
||||||
lineWidth: 3,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -5,5 +5,20 @@ export const API_TIMEOUT = 10000;
|
|||||||
// 图谱渲染配置
|
// 图谱渲染配置
|
||||||
export const GRAPH_DEFAULT_HEIGHT = 600;
|
export const GRAPH_DEFAULT_HEIGHT = 600;
|
||||||
|
|
||||||
|
// 节点大小配置
|
||||||
|
export const DEFAULT_NODE_SIZE = 50;
|
||||||
|
export const NODE_SIZE_MIN = 10;
|
||||||
|
export const NODE_SIZE_MAX = 60;
|
||||||
|
|
||||||
|
// 边宽度配置
|
||||||
|
export const DEFAULT_EDGE_WIDTH = 1.5;
|
||||||
|
export const EDGE_WIDTH_MIN = 1;
|
||||||
|
export const EDGE_WIDTH_MAX = 2;
|
||||||
|
|
||||||
|
// Importance 配置
|
||||||
|
export const IMPORTANCE_DEFAULT = 0.8;
|
||||||
|
export const IMPORTANCE_MIN = 0;
|
||||||
|
export const IMPORTANCE_MAX = 1;
|
||||||
|
|
||||||
// 搜索相关常量
|
// 搜索相关常量
|
||||||
export const SEARCH_RESULT_MAX_HEIGHT = 256; // 16rem
|
export const SEARCH_RESULT_MAX_HEIGHT = 256; // 16rem
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import type { Node } from '../types/graph';
|
||||||
|
import {
|
||||||
|
NODE_SIZE_MIN,
|
||||||
|
NODE_SIZE_MAX,
|
||||||
|
EDGE_WIDTH_MIN,
|
||||||
|
EDGE_WIDTH_MAX,
|
||||||
|
IMPORTANCE_MIN,
|
||||||
|
IMPORTANCE_MAX,
|
||||||
|
} from '../config/constants';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 归一化值到 [0,1] 范围
|
||||||
|
*/
|
||||||
|
function normalizeValue(value: number, min: number, max: number): number {
|
||||||
|
if (isNaN(value) || !isFinite(value)) {
|
||||||
|
return 0.5;
|
||||||
|
}
|
||||||
|
const clamped = Math.max(min, Math.min(max, value));
|
||||||
|
return (clamped - min) / (max - min);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 反归一化值从 [0,1] 到目标范围
|
||||||
|
*/
|
||||||
|
function denormalizeValue(value: number, min: number, max: number): number {
|
||||||
|
if (isNaN(value) || !isFinite(value)) {
|
||||||
|
return (min + max) / 2;
|
||||||
|
}
|
||||||
|
const clamped = Math.max(0, Math.min(1, value));
|
||||||
|
return clamped * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算节点大小
|
||||||
|
*/
|
||||||
|
export function calculateNodeSize(properties?: any): number {
|
||||||
|
const importance = properties?.importance ?? IMPORTANCE_MAX;
|
||||||
|
const normalized = normalizeValue(importance, IMPORTANCE_MIN, IMPORTANCE_MAX);
|
||||||
|
const size = denormalizeValue(normalized, NODE_SIZE_MIN, NODE_SIZE_MAX) ?? NODE_SIZE_MIN;
|
||||||
|
return Math.round(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算边的宽度
|
||||||
|
*/
|
||||||
|
export function calculateEdgeWidth(sourceProperties?: any, targetProperties?: any): number {
|
||||||
|
const sourceImportance = sourceProperties?.importance ?? IMPORTANCE_MAX;
|
||||||
|
const targetImportance = targetProperties?.importance ?? IMPORTANCE_MAX;
|
||||||
|
const avgImportance = (sourceImportance + targetImportance) / 2;
|
||||||
|
const normalized = normalizeValue(avgImportance, IMPORTANCE_MIN, IMPORTANCE_MAX);
|
||||||
|
const width = denormalizeValue(normalized, EDGE_WIDTH_MIN, EDGE_WIDTH_MAX) ?? EDGE_WIDTH_MIN;
|
||||||
|
return parseFloat(width.toFixed(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G6 节点动态样式配置函数
|
||||||
|
* 根据 G6 文档推荐的动态配置方式实现
|
||||||
|
*/
|
||||||
|
export const getNodeStyle = () => ({
|
||||||
|
size: (datum: any) => {
|
||||||
|
const size = calculateNodeSize(datum.data?.properties);
|
||||||
|
return size;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* G6 边动态样式配置函数
|
||||||
|
* 根据 G6 文档推荐的动态配置方式实现
|
||||||
|
*/
|
||||||
|
export const getEdgeStyle = (nodeMap: Map<string, Node>) => ({
|
||||||
|
lineWidth: (datum: any) => {
|
||||||
|
const sourceNode = nodeMap.get(datum.source);
|
||||||
|
const targetNode = nodeMap.get(datum.target);
|
||||||
|
return calculateEdgeWidth(sourceNode?.properties, targetNode?.properties);
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user