feat: Alter style of ForceGraph #162 (#1774)

### What problem does this PR solve?

feat: alter style of ForceGraph #162
### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2024-08-01 19:24:03 +08:00 committed by GitHub
parent e37b0d217d
commit e8b9871fb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 54 additions and 49 deletions

View File

@ -1,25 +1,19 @@
import { Graph } from '@antv/g6';
import { useSize } from 'ahooks';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import { graphData } from './constant';
import { Converter, buildNodesAndCombos, isDataExist } from './util';
import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks'; import { useFetchKnowledgeGraph } from '@/hooks/chunk-hooks';
import { ElementDatum, Graph, IElementEvent } from '@antv/g6';
import { useCallback, useEffect, useMemo, useRef } from 'react';
import { buildNodesAndCombos, isDataExist } from './util';
import styles from './index.less'; import styles from './index.less';
const converter = new Converter(); const TooltipColorMap = {
combo: 'red',
const nextData = converter.buildNodesAndCombos( node: 'black',
graphData.nodes, edge: 'blue',
graphData.edges, };
);
console.log('🚀 ~ nextData:', nextData);
const finalData = { ...graphData, ...nextData };
const ForceGraph = () => { const ForceGraph = () => {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const size = useSize(containerRef); const graphRef = useRef<Graph | null>(null);
const { data } = useFetchKnowledgeGraph(); const { data } = useFetchKnowledgeGraph();
const nextData = useMemo(() => { const nextData = useMemo(() => {
@ -30,12 +24,12 @@ const ForceGraph = () => {
} }
return { nodes: [], edges: [] }; return { nodes: [], edges: [] };
}, [data]); }, [data]);
console.log('🚀 ~ nextData ~ nextData:', nextData);
const render = useCallback(() => { const render = useCallback(() => {
const graph = new Graph({ const graph = new Graph({
container: containerRef.current!, container: containerRef.current!,
autoFit: 'view', autoFit: 'view',
autoResize: true,
behaviors: [ behaviors: [
'drag-element', 'drag-element',
'drag-canvas', 'drag-canvas',
@ -49,16 +43,23 @@ const ForceGraph = () => {
plugins: [ plugins: [
{ {
type: 'tooltip', type: 'tooltip',
getContent: (e, items) => { enterable: true,
if (items.every((x) => x?.description)) { getContent: (e: IElementEvent, items: ElementDatum) => {
if (Array.isArray(items)) {
let result = ``; let result = ``;
items.forEach((item) => { items.forEach((item) => {
result += `<h3>${item?.id}</h3>`; result += `<section style="color:${TooltipColorMap[e['targetType'] as keyof typeof TooltipColorMap]};"><h3>${item?.id}</h3>`;
if (item?.entity_type) {
result += `<div style="padding-bottom: 6px;"><b>Entity type: </b>${item?.entity_type}</div>`;
}
if (item?.weight) {
result += `<div><b>Weight: </b>${item?.weight}</div>`;
}
if (item?.description) { if (item?.description) {
result += `<p>${item?.description}</p>`; result += `<p>${item?.description}</p>`;
} }
}); });
return result; return result + '</section>';
} }
return undefined; return undefined;
}, },
@ -68,44 +69,44 @@ const ForceGraph = () => {
type: 'combo-combined', type: 'combo-combined',
preventOverlap: true, preventOverlap: true,
comboPadding: 1, comboPadding: 1,
spacing: 20, spacing: 100,
}, },
node: { node: {
style: { style: {
size: 20, size: 150,
labelText: (d) => d.id, labelText: (d) => d.id,
labelPadding: 30, // labelPadding: 30,
labelFontSize: 40,
// labelOffsetX: 20, // labelOffsetX: 20,
// labelOffsetY: 5, labelOffsetY: 20,
labelPlacement: 'center', labelPlacement: 'center',
labelWordWrap: true, labelWordWrap: true,
}, },
palette: { palette: {
type: 'group', type: 'group',
field: (d) => d.combo, field: (d) => {
return d?.entity_type as string;
},
}, },
// state: {
// highlight: {
// fill: '#D580FF',
// halo: true,
// lineWidth: 0,
// },
// dim: {
// fill: '#99ADD1',
// },
// },
}, },
edge: { edge: {
style: (model) => { style: (model) => {
const { size, color } = model.data; const weight: number = Number(model?.weight) || 2;
const lineWeight = weight * 4;
return { return {
stroke: color || '#99ADD1', stroke: '#99ADD1',
lineWidth: size || 1, lineWidth: lineWeight > 10 ? 10 : lineWeight,
}; };
}, },
}, },
}); });
if (graphRef.current) {
graphRef.current.destroy();
}
graphRef.current = graph;
graph.setData(nextData); graph.setData(nextData);
graph.render(); graph.render();
@ -117,7 +118,13 @@ const ForceGraph = () => {
} }
}, [data, render]); }, [data, render]);
return <div ref={containerRef} className={styles.forceContainer} />; return (
<div
ref={containerRef}
className={styles.forceContainer}
style={{ width: '100%', height: '80vh' }}
/>
);
}; };
export default ForceGraph; export default ForceGraph;

View File

@ -1,9 +1,10 @@
.forceContainer { .forceContainer {
width: 100%; :global(.tooltip) {
height: 100%; border-radius: 10px !important;
}
} }
.modalContainer { .modalContainer {
width: 90vw; width: 100%;
height: 80vh; height: 100%;
} }

View File

@ -4,6 +4,7 @@ import React, { useEffect, useState } from 'react';
import ForceGraph from './force-graph'; import ForceGraph from './force-graph';
import styles from './index.less'; import styles from './index.less';
import { isDataExist } from './util';
const KnowledgeGraphModal: React.FC = () => { const KnowledgeGraphModal: React.FC = () => {
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
@ -18,8 +19,7 @@ const KnowledgeGraphModal: React.FC = () => {
}; };
useEffect(() => { useEffect(() => {
if (data?.data && typeof data?.data !== 'boolean') { if (isDataExist(data)) {
console.log('🚀 ~ useEffect ~ data:', data);
setIsModalOpen(true); setIsModalOpen(true);
} }
}, [setIsModalOpen, data]); }, [setIsModalOpen, data]);

View File

@ -65,9 +65,6 @@ export const buildNodesAndCombos = (nodes: any[]) => {
if (combo && combos.every((y) => y.id !== combo)) { if (combo && combos.every((y) => y.id !== combo)) {
combos.push({ combos.push({
id: combo, id: combo,
data: {
label: `Combo ${combo}`,
},
}); });
} }
return { return {