diff --git a/packages/gi-assets-basic/src/elements/SimpleEdge/registerTransform.ts b/packages/gi-assets-basic/src/elements/SimpleEdge/registerTransform.ts index 5b3dcc7d9..4a2d6da3d 100644 --- a/packages/gi-assets-basic/src/elements/SimpleEdge/registerTransform.ts +++ b/packages/gi-assets-basic/src/elements/SimpleEdge/registerTransform.ts @@ -214,7 +214,7 @@ const transform = (config: GIEdgeConfig, reset?: boolean) => { }, preStyle, ); - console.log('edge.......', edge, finalStyle); + console.log('edge.......', id); return { source, diff --git a/packages/gi-assets-basic/src/elements/SimpleNode/registerTransform.ts b/packages/gi-assets-basic/src/elements/SimpleNode/registerTransform.ts index b3092c8af..1b2ce9b04 100644 --- a/packages/gi-assets-basic/src/elements/SimpleNode/registerTransform.ts +++ b/packages/gi-assets-basic/src/elements/SimpleNode/registerTransform.ts @@ -263,7 +263,7 @@ const transform = (nodeConfig: GINodeConfig, reset?: boolean) => { }, }, }; - console.log('keyshape', keyshape.type, keyshape); + console.log('keyshape', node.id); return { id: node.id, data: { @@ -275,7 +275,7 @@ const transform = (nodeConfig: GINodeConfig, reset?: boolean) => { position: label.position || 'bottom', }, keyShape: { - r: keyshape.size || 10, + r: keyshape.size / 2 || 10, fill: keyshape.fill || 'red', stroke: keyshape.stroke || 'red', strokeOpacity: keyshape.strokeOpacity || 1, diff --git a/packages/gi-sdk/src/GISDK.tsx b/packages/gi-sdk/src/GISDK.tsx index 10e1633c2..6375d16b2 100644 --- a/packages/gi-sdk/src/GISDK.tsx +++ b/packages/gi-sdk/src/GISDK.tsx @@ -1,15 +1,13 @@ import Graphin, { GraphinContext } from '@antv/graphin'; -import React, { useEffect, useMemo, useRef } from 'react'; +import React, { useEffect, useMemo } from 'react'; import { IntlProvider, useIntl } from 'react-intl'; import { useImmer } from 'use-immer'; -import { defaultInitializerCfg } from './Initializer'; import { deepClone } from './components/const'; import getComponents from './hooks/useComponents'; import './index.less'; -import * as utils from './process'; import { createUuid } from './process/common'; import { getMapperByCfg } from './process/getMapperByCfg'; -import type { GIComponentConfig, GIGraphData, Props, State } from './typing'; +import type { GIGraphData, Props, State } from './typing'; let updateHistoryTimer: number; @@ -35,34 +33,11 @@ const getComponentsCfg = (componentsCfg, pageLayout) => { return { componentsCfg, GICC_LAYOUT, INITIALIZER }; }; -const getTransformer = (nodesCfg, edgesCfg, ElementAssets) => { - /** - * - * @param data 源数据 - * @param reset 是否重置:按照 Node/Edge Schema来视觉映射 - * @returns - */ - const transform = (data, reset?: boolean) => { - const nodes = utils.transDataByConfig('nodes', data, { nodes: nodesCfg, edges: edgesCfg }, ElementAssets, reset); - const edges = utils.transDataByConfig('edges', data, { nodes: nodesCfg, edges: edgesCfg }, ElementAssets, reset); - - const { combos, tableResult } = data; - - return { - nodes, - edges, - combos, - tableResult, - }; - }; - return transform; -}; -/** export */ const GISDK = (props: Props) => { - const graphRef = useRef(null); - const { children, assets, id, services, config, locales } = props; + const { children, assets, id, services, locales } = props; const { language = 'zh-CN', ...localeMessages } = locales || {}; + /** get gisdk id */ const GISDK_ID = React.useMemo(() => { if (!id) { const defaultId = `${Math.random().toString(36).substr(2)}`; @@ -87,156 +62,44 @@ const GISDK = (props: Props) => { }, HAS_GRAPH: false, source: { nodes: [], edges: [] } as GIGraphData, - layout: {}, - components: [] as GIComponentConfig[], config: props.config, isLoading: false, isContextReady: false, initialized: false, - initializer: defaultInitializerCfg, - transform: (data, reset?: boolean) => data, layoutCache: false, largeGraphLimit: 2000, largeGraphData: undefined, - GICC_LAYOUT: { - id: 'EmptyLayout', - props: {}, - }, - //@ts-ignore - GISDK_ID, //@ts-ignore nodeMapper: null, }); - const { data, layout, components, initializer, theme, transform, GICC_LAYOUT, HAS_GRAPH, graph } = state; + const { data, HAS_GRAPH, graph, config } = state; + /** 计算逻辑 */ + const { layout: layoutCfg, components: componentsCfg = [], nodes: nodesCfg, edges: edgesCfg, pageLayout } = config; - useEffect(() => { + const handleGraphInit = ins => { updateState(draft => { - draft.config = config; + draft.graph = ins; + draft.HAS_GRAPH = true; }); - }, [config]); + }; useEffect(() => { - // init... - - console.log('%c GISDK INTI ....', 'color:rgba(255,87,34,0.8)', graphRef); - - const { assets, config, services } = props; - - const { GICC_LAYOUT, INITIALIZER, componentsCfg } = getComponentsCfg(config.components, config.pageLayout); - const transform = getTransformer(config.nodes, config.edges, ElementAssets); - const nodeMapper = getMapperByCfg(config.nodes, ElementAssets); - const edgeMapper = getMapperByCfg(config.edges, ElementAssets); + console.log('gisdk props config change.....'); updateState(draft => { - /** initializer */ - if (INITIALIZER.id !== draft.initializer?.id) { - draft.initializer = INITIALIZER; - } - /** components */ - draft.config.components = componentsCfg; - draft.components = componentsCfg; - /** layout */ - draft.config.layout = config.layout; - draft.layout = config.layout.props || {}; - draft.layoutCache = false; - /** styling */ - draft.transform = transform; - draft.config.nodes = config.nodes; - draft.config.edges = config.edges; - // if (draft.data.nodes.length !== 0) { - // const preData = original(draft.data); - // // 当节点和边的Schema配置变化的时候,默认是重置视觉映射; - // const newData = transform(preData, true); - // //@ts-ignore - // draft.data = newData; - // } - - draft.GICC_LAYOUT = GICC_LAYOUT; - /** props */ - draft.config = config; - draft.servives = services; - /** flag */ - draft.graph = graphRef.current; - draft.HAS_GRAPH = true; - draft.nodeMapper = nodeMapper; - draft.edgeMapper = edgeMapper; + draft.config = props.config; }); - }, []); + }, [props.config]); - const { - layout: layoutCfg, - components: componentsCfg = [], - nodes: nodesCfg, - edges: edgesCfg, - pageLayout, - } = state.config; - /** 根据注册的图元素,生成Transform函数 */ - - React.useEffect(() => { - if (!HAS_GRAPH) { - return; - } - console.log('%c GISDK COMPONENTS ....', 'color:rgba(255,87,34,0.8)'); + const { GICC_LAYOUT, INITIALIZER, ComponentCfg } = useMemo(() => { const { GICC_LAYOUT, INITIALIZER, componentsCfg: ComponentCfg } = getComponentsCfg(componentsCfg, pageLayout); - - updateState(draft => { - draft.config.components = ComponentCfg; - draft.components = ComponentCfg; - if (INITIALIZER.id !== draft.initializer?.id) { - //@ts-ignore - draft.initializer = INITIALIZER; - } - draft.layoutCache = true; - //@ts-ignore - draft.GICC_LAYOUT = GICC_LAYOUT; - }); + return { + GICC_LAYOUT, + INITIALIZER, + ComponentCfg, + }; }, [componentsCfg, pageLayout, HAS_GRAPH]); - React.useEffect(() => { - if (!layoutCfg || !HAS_GRAPH) { - return; - } - console.log('%c GISDK LAYOUT ....', 'color:rgba(255,87,34,0.8)'); - stopForceSimulation(); - const { type, ...options } = layoutCfg.props || {}; - let otherOptions = {}; - - updateState(draft => { - draft.config.layout = layoutCfg; - draft.layout = layoutCfg.props; - draft.layoutCache = false; - }); - }, [layoutCfg, HAS_GRAPH]); - - /** 增加多元素 */ - React.useEffect(() => { - if (!nodesCfg || !edgesCfg || nodesCfg.length === 0 || edgesCfg.length === 0 || !HAS_GRAPH) { - return; - } - console.log('%c GISDK STYLE ....', 'color:rgba(255,87,34,0.8)'); - - const nodeMapper = getMapperByCfg(nodesCfg, ElementAssets); - const edgeMapper = getMapperByCfg(edgesCfg, ElementAssets); - - const transform = getTransformer(nodesCfg, edgesCfg, ElementAssets); - - updateState(draft => { - // if (draft.data.nodes.length !== 0) { - // const preData = original(draft.data); - // // 当节点和边的Schema配置变化的时候,默认是重置视觉映射; - // const newData = transform(preData, true); - // //@ts-ignore - // draft.data = newData; - // } - draft.transform = transform; - draft.config.nodes = nodesCfg; - draft.config.edges = edgesCfg; - draft.nodeMapper = nodeMapper; - draft.edgeMapper = edgeMapper; - }); - }, [nodesCfg, edgesCfg, HAS_GRAPH]); - - // console.log('%c G6VP Render...', 'color:red', state.layout); const sourceDataMap = useMemo(() => { const nodes = state.source.nodes.reduce((acc, cur) => { acc[cur.id] = cur; @@ -302,11 +165,11 @@ const GISDK = (props: Props) => { assets, sourceDataMap, HAS_GRAPH, - graph: graph, + graph, updateContext: updateState, updateData: res => { updateState(draft => { - const newData = transform(res); + const newData = res; draft.data = newData; draft.source = newData; draft.layoutCache = false; @@ -314,16 +177,16 @@ const GISDK = (props: Props) => { }, updateLayout: res => { updateState(draft => { - draft.layout = res; + draft.config.layout = res; draft.layoutCache = false; }); }, updateDataAndLayout: (res, lay) => { updateState(draft => { - const newData = transform(res); + const newData = res; draft.data = newData; draft.source = newData; - draft.layout = lay; + draft.config.layout = lay; draft.layoutCache = false; }); }, @@ -354,35 +217,44 @@ const GISDK = (props: Props) => { useIntl, language, }; - if (!ComponentAssets) { - return null; - } - const layout2 = useMemo(() => deepClone(layout), [layout]); + const layout2 = useMemo(() => { + return deepClone(layoutCfg.props); + }, [layoutCfg]); const { renderComponents, InitializerComponent, InitializerProps, GICC_LAYOUT_COMPONENT, GICC_LAYOUT_PROPS } = - getComponents({ ...state, HAS_GRAPH }, config.components, ComponentAssets); + getComponents({ + config: { pageLayout, components: ComponentCfg }, + initializer: INITIALIZER, + GICC_LAYOUT, + components: ComponentCfg, + GISDK_ID, + propsComponentsCfg: ComponentCfg, + ComponentAssets, + }); + + /** 节点样式映射 */ + const nodeMapper = useMemo(() => getMapperByCfg(nodesCfg, ElementAssets), [nodesCfg]); + /** 边样式映射 */ + const edgeMapper = useMemo(() => getMapperByCfg(edgesCfg, ElementAssets), [edgesCfg]); return (
{/* @ts-ignore */} {/* @ts-ignore */} - {HAS_GRAPH && } {HAS_GRAPH && state.initialized && renderComponents()} diff --git a/packages/gi-sdk/src/components/SimpleEdge/registerTransform.ts b/packages/gi-sdk/src/components/SimpleEdge/registerTransform.ts index 90ebdb62a..1b4cf8667 100644 --- a/packages/gi-sdk/src/components/SimpleEdge/registerTransform.ts +++ b/packages/gi-sdk/src/components/SimpleEdge/registerTransform.ts @@ -59,13 +59,15 @@ export const defaultConfig = { export type EdgeConfig = typeof defaultConfig; /** 数据映射函数 需要根据配置自动生成*/ -const transform = (edges, config: GIEdgeConfig, reset?: boolean) => { +const transform = (config: GIEdgeConfig, reset?: boolean) => { try { - const { color: color_CFG, size: size_CFG, label: LABEL_KEYS, advanced, status: defaultStatus } = defaultConfig; + const { color: color_CFG, size: size_CFG, label: LABEL_KEYS, advanced, status: defaultStatus } = config.props; const { keyshape: keyshape_CFG } = advanced; - const transEdge = (edge, index) => { + const transEdge = (_edge, index) => { + console.log('transEdge.....'); + const edge = _edge.data; // properties const { source, target } = edge; const id = edge.id || `${source}-${target}-${index}`; @@ -180,14 +182,50 @@ const transform = (edges, config: GIEdgeConfig, reset?: boolean) => { preStyle = {}; } + const finalStyle = { + keyshape: { + ...shape, + // ...edge.style?.keyshape, + lineWidth: size_CFG, + stroke: color_CFG, + opacity: keyshape_CFG.opacity, + lineDash: keyshape_CFG.lineDash, + lineAppendWidth: 10, //keyshape_CFG.lineAppendWidth, + ...endArrow, + }, + label, + animate: { + visible: advanced.animate.visible, + type: advanced.animate.type, + color: advanced.animate.dotColor, + repeat: advanced.animate.repeat, + duration: advanced.animate.duration, + }, + status: { + ...defaultStatus, + }, + }; + console.log('edge.......', edge, finalStyle); + return { - ...edge, source, target, id, - data, - type: 'graphin-line', - edgeType: edge.edgeType || 'UNKOWN', + data: { + type: 'line-edge', + edgeType: edge.edgeType || 'UNKOWN', + style: finalStyle, + keyShape: { + lineWidth: finalStyle.keyshape.lineWidth, + stroke: finalStyle.keyshape.stroke, + endArrow: true, + }, + haloShape: {}, + labelShape: { + text: finalStyle.label.value, + }, + labelBackgroundShape: {}, + }, }; }; return transEdge; diff --git a/packages/gi-sdk/src/components/SimpleNode/registerTransform.ts b/packages/gi-sdk/src/components/SimpleNode/registerTransform.ts index 9352a5d37..2c8f3add1 100644 --- a/packages/gi-sdk/src/components/SimpleNode/registerTransform.ts +++ b/packages/gi-sdk/src/components/SimpleNode/registerTransform.ts @@ -127,6 +127,7 @@ export const defaultConfig = { keyshape: { ...keyshape, fillOpacity: 0.8, + type: 'circle-node', }, label: { ...label, @@ -179,7 +180,7 @@ const transform = (nodeConfig: GINodeConfig, reset?: boolean) => { try { /** 解构配置项 */ - const { color, size, label: LABEL_KEYS, advanced, status: userStatus } = defaultConfig; + const { color, size, label: LABEL_KEYS, advanced, status: userStatus } = nodeConfig.props; let isBug = false; //@ts-ignore @@ -188,6 +189,7 @@ const transform = (nodeConfig: GINodeConfig, reset?: boolean) => { } const { halo } = isBug ? defaultConfig.advanced : advanced; const transNode = node => { + console.log('transNode.....'); // properties const data = node.data || node.properties || node; @@ -254,14 +256,40 @@ const transform = (nodeConfig: GINodeConfig, reset?: boolean) => { }, }, }; - + console.log('keyshape', keyshape.type, keyshape); return { - ...node, id: node.id, - data, - nodeType: node.nodeType || 'UNKNOW', - type: 'circle-node', - // 数据中的style还是优先级最高的 + data: { + type: keyshape.type, + x: data.x, + y: data.y, + labelShape: { + text: label.value || '', + position: label.position || 'bottom', + }, + keyShape: { + r: keyshape.size || 10, + fill: keyshape.fill || 'red', + stroke: keyshape.stroke || 'red', + strokeOpacity: keyshape.strokeOpacity || 1, + }, + animates: { + update: [ + { + fields: ['x', 'y'], + shapeId: 'group', + }, + // { + // fields: ['opacity'], + // shapeId: 'haloShape', + // }, + // { + // fields: ['lineWidth'], + // shapeId: 'keyShape', + // }, + ], + }, + }, }; }; return transNode; diff --git a/packages/gi-sdk/src/hooks/useComponents.tsx b/packages/gi-sdk/src/hooks/useComponents.tsx index 105fd44c4..b4d8d17d9 100644 --- a/packages/gi-sdk/src/hooks/useComponents.tsx +++ b/packages/gi-sdk/src/hooks/useComponents.tsx @@ -11,8 +11,15 @@ const DEFAULT_GICC_LAYOUT = { }, }; -const useComponents = (state, propsComponentsCfg, ComponentAssets) => { - const { config, initializer, GICC_LAYOUT, components, GISDK_ID } = state; +const useComponents = ({ + config, + initializer, + GICC_LAYOUT, + components, + GISDK_ID, + propsComponentsCfg, + ComponentAssets, +}) => { const { components: stateComponentsCfg } = config; const ComponentCfgMap = propsComponentsCfg.concat(stateComponentsCfg).reduce((acc, curr) => { return { diff --git a/packages/gi-sdk/src/typing.ts b/packages/gi-sdk/src/typing.ts index e7105ebb2..3d9c2d39a 100644 --- a/packages/gi-sdk/src/typing.ts +++ b/packages/gi-sdk/src/typing.ts @@ -1,5 +1,5 @@ import type { ComboModel as Combo } from '@antv/g6'; -import type { GraphinContextType, GraphinData, IUserEdge, IUserNode, Layout } from '@antv/graphin'; +import type { GraphinContextType, GraphinData, IUserEdge, IUserNode } from '@antv/graphin'; import type { LANGUAGE_KEY_NAME } from './process/locale'; import type { GraphSchemaData, IGraphData } from './process/schema'; export type { GraphSchemaData }; @@ -39,25 +39,10 @@ export interface State< schemaData: GraphSchemaData; - /** 布局 */ - layout: Layout; - /** 组件 */ - components: GIComponentConfig[]; HAS_GRAPH: boolean; /** 画布是否初始化完成 */ initialized: boolean; - /** 图初始化组件 */ - initializer: { - id: string; - props: { - GI_INITIALIZER: boolean; - serviceId: 'GI_SERVICE_INTIAL_GRAPH' | string; - }; - }; - GICC_LAYOUT: { - id: string; - props: any; - }; + /** 画布的配置,等同props.config */ config: GIConfig; /** 画布所有注册的服务 */ @@ -66,15 +51,9 @@ export interface State< isLoading: boolean; /** 图的上下文准备 */ isContextReady: boolean; - /** - * 数据映射函数 - */ - transform: (data: any, reset?: boolean) => any; /** 是否使用缓存的布局 */ layoutCache: boolean; - nodeMapper: (n: any) => any; - edgeMapper: (n: any) => any; } export interface Props { diff --git a/packages/graphin/src/Graphin.tsx b/packages/graphin/src/Graphin.tsx index cd660deba..b90ee5d0a 100644 --- a/packages/graphin/src/Graphin.tsx +++ b/packages/graphin/src/Graphin.tsx @@ -36,8 +36,11 @@ const Graphin: React.FunctionComponent = forwardRef((props, ref) = const dataRef = useRef(data); const layoutRef = useRef(layout); - const nodeMapperRef = useRef(node); - const edgeMapperRef = useRef(edge); + + const constantRef = useRef({ + AFTER_RENDER_NODE_MAPPER: false, + AFTER_RENDER_EDGE_MAPPER: false, + }); const [state, setState] = useState<{ isReady: boolean; @@ -47,39 +50,53 @@ const Graphin: React.FunctionComponent = forwardRef((props, ref) = graph: null, })); const { isReady, graph } = state; - console.log('%c GRAPHIN RENDER....', 'color:rgba(48,86,227,1)', nodeMapperRef.current, node); + + if (dataRef.current !== data) { + // console.log('%c GRAPHIN DATA CHANGE....', 'color:rgba(48,86,227,0.8)', dataRef.current, data); + console.time('GRAPHIN_CHANGE_DATA_COST'); + //@ts-ignore + graph && graph.changeData(data, 'replace'); + //@ts-ignore + dataRef.current = data; + console.timeEnd('GRAPHIN_CHANGE_DATA_COST'); + } + if (layoutRef.current !== layout) { + // console.log('%c GRAPHIN LAYOUT CHANGE....', 'color:rgba(48,86,227,0.8)'); + console.time('GRAPHIN_CHANGE_LAYOUT_COST'); + //@ts-ignore + graph && graph.layout(layout); + //@ts-ignore + layoutRef.current = layout; + console.timeEnd('GRAPHIN_CHANGE_LAYOUT_COST'); + } useEffect(() => { - if (nodeMapperRef.current !== node) { - console.log('%c GRAPHIN NODE MAPPER CHANGE....', 'color:rgba(48,86,227,0.8)', node, graph); - //@ts-ignore - graph && graph.updateMapper('node', node); - nodeMapperRef.current = node; - } - if (edgeMapperRef.current !== edge) { - console.log('%c GRAPHIN EDGE MAPPER CHANGE....', 'color:rgba(48,86,227,0.8)'); - //@ts-ignore - graph && graph.updateMapper('edge', edge); - edgeMapperRef.current = edge; + if (graph) { + if (constantRef.current.AFTER_RENDER_EDGE_MAPPER) { + graph.updateMapper('edge', edge); + } else { + graph.once('afterrender', e => { + constantRef.current.AFTER_RENDER_EDGE_MAPPER = true; + setTimeout(() => { + graph.updateMapper('edge', edge); + }, 0); + }); + } } - if (dataRef.current !== data) { - // console.log('%c GRAPHIN DATA CHANGE....', 'color:rgba(48,86,227,0.8)', dataRef.current, data); - console.time('GRAPHIN_CHANGE_DATA_COST'); - //@ts-ignore - graph && graph.changeData(data, 'replace'); - //@ts-ignore - dataRef.current = data; - console.timeEnd('GRAPHIN_CHANGE_DATA_COST'); - } - if (layoutRef.current !== layout) { - // console.log('%c GRAPHIN LAYOUT CHANGE....', 'color:rgba(48,86,227,0.8)'); - console.time('GRAPHIN_CHANGE_LAYOUT_COST'); - //@ts-ignore - graph && graph.layout(layout); - //@ts-ignore - layoutRef.current = layout; - console.timeEnd('GRAPHIN_CHANGE_LAYOUT_COST'); + }, [edge, graph]); + useEffect(() => { + if (graph) { + if (constantRef.current.AFTER_RENDER_NODE_MAPPER) { + graph.updateMapper('node', node); + } else { + graph.once('afterrender', e => { + constantRef.current.AFTER_RENDER_NODE_MAPPER = true; + setTimeout(() => { + graph.updateMapper('node', node); + }, 0); + }); + } } - }, [data, layout, node, edge]); + }, [node, graph]); useEffect(() => { let { @@ -102,15 +119,10 @@ const Graphin: React.FunctionComponent = forwardRef((props, ref) = height, modes, data, - // //@ts-ignore - // node, - // // //@ts-ignore - // edge, layout, renderer, transforms: ['transform-graphin-data'], }); - console.log('init ...', instance, ref); /** @ts-ignore 做兼容性处理 */ Compatible.graph(instance); @@ -131,13 +143,6 @@ const Graphin: React.FunctionComponent = forwardRef((props, ref) = }; }); - instance.once('afterrender', e => { - console.log('afterlayout', nodeMapperRef.current, edgeMapperRef.current); - //@ts-ignore - instance.updateMapper('node', nodeMapperRef.current); - //@ts-ignore - instance.updateMapper('edge', edgeMapperRef.current); - }); return () => { console.log('%c GRAPHIN DESTORY....', 'color:rgba(48,86,227,1)'); instance.destroy();