diff --git a/src/chart/sankey/SankeySeries.ts b/src/chart/sankey/SankeySeries.ts index 9dca447cad..5e08b6298d 100644 --- a/src/chart/sankey/SankeySeries.ts +++ b/src/chart/sankey/SankeySeries.ts @@ -61,7 +61,7 @@ interface SankeyEdgeStyleOption extends LineStyleOption { interface ExtraStateOption { emphasis?: { - focus?: DefaultEmphasisFocus | 'adjacency' | 'trajectory' + focus?: DefaultEmphasisFocus | 'adjacency' | 'trajectory' | 'trajectoryColor' } } diff --git a/src/chart/sankey/SankeyView.ts b/src/chart/sankey/SankeyView.ts index 89e457d497..52e0bcdb5f 100644 --- a/src/chart/sankey/SankeyView.ts +++ b/src/chart/sankey/SankeyView.ts @@ -243,6 +243,7 @@ class SankeyView extends ChartView { curve, focus === 'adjacency' ? edge.getAdjacentDataIndices() : focus === 'trajectory' ? edge.getTrajectoryDataIndices() + : focus === 'trajectoryColor' ? edge.getTrajectoryColorDataIndices() : focus, emphasisModel.get('blurScope'), emphasisModel.get('disabled') @@ -300,6 +301,8 @@ class SankeyView extends ChartView { ? node.getAdjacentDataIndices() : focus === 'trajectory' ? node.getTrajectoryDataIndices() + : focus === 'trajectoryColor' + ? node.getTrajectoryColorDataIndices() : focus, emphasisModel.get('blurScope'), emphasisModel.get('disabled') diff --git a/src/data/Graph.ts b/src/data/Graph.ts index 3c6de5ca59..6ca0496b34 100644 --- a/src/data/Graph.ts +++ b/src/data/Graph.ts @@ -432,6 +432,74 @@ class GraphNode { node: connectedNodesMap.keys() }; } + + getTrajectoryColorDataIndices(): {node: number[], edge: number[]} { + const connectedEdgesMap = zrUtil.createHashMap(); + const connectedNodesMap = zrUtil.createHashMap(); + + const data = this.hostGraph.data; + const getColor = (index: number) => { + const rawData: any = data.getRawDataItem(index); + return rawData?.itemStyle?.color; + }; + const currentNodeColor = getColor(this.dataIndex); + + for (let i = 0; i < this.edges.length; i++) { + const adjacentEdge = this.edges[i]; + if (adjacentEdge.dataIndex < 0) { + continue; + } + const sourceNodeColor = getColor(adjacentEdge.node1.dataIndex); + const targetNodeColor = getColor(adjacentEdge.node2.dataIndex); + if (sourceNodeColor === currentNodeColor || targetNodeColor === currentNodeColor) { + connectedEdgesMap.set(adjacentEdge.dataIndex, true); + } + + const sourceNodesQueue = [adjacentEdge.node1]; + const targetNodesQueue = [adjacentEdge.node2]; + + let nodeIteratorIndex = 0; + while (nodeIteratorIndex < sourceNodesQueue.length) { + const sourceNode = sourceNodesQueue[nodeIteratorIndex]; + nodeIteratorIndex++; + if (getColor(sourceNode.dataIndex) === currentNodeColor) { + connectedNodesMap.set(sourceNode.dataIndex, true); + } + + for (let j = 0; j < sourceNode.inEdges.length; j++) { + const sourceNodeColor = getColor(sourceNode.inEdges[j].node1.dataIndex); + const targetNodeColor = getColor(sourceNode.inEdges[j].node2.dataIndex); + if (sourceNodeColor === currentNodeColor || targetNodeColor === currentNodeColor) { + connectedEdgesMap.set(sourceNode.inEdges[j].dataIndex, true); + } + sourceNodesQueue.push(sourceNode.inEdges[j].node1); + } + } + + nodeIteratorIndex = 0; + while (nodeIteratorIndex < targetNodesQueue.length) { + const targetNode = targetNodesQueue[nodeIteratorIndex]; + nodeIteratorIndex++; + if (getColor(targetNode.dataIndex) === currentNodeColor) { + connectedNodesMap.set(targetNode.dataIndex, true); + } + for (let j = 0; j < targetNode.outEdges.length; j++) { + connectedEdgesMap.set(targetNode.outEdges[j].dataIndex, true); + const sourceNodeColor = getColor(targetNode.outEdges[j].node1.dataIndex); + const targetNodeColor = getColor(targetNode.outEdges[j].node2.dataIndex); + if (sourceNodeColor === currentNodeColor || targetNodeColor === currentNodeColor) { + connectedEdgesMap.set(targetNode.outEdges[j].dataIndex, true); + } + targetNodesQueue.push(targetNode.outEdges[j].node2); + } + } + } + + return { + edge: connectedEdgesMap.keys(), + node: connectedNodesMap.keys() + }; + } } @@ -515,6 +583,70 @@ class GraphEdge { node: connectedNodesMap.keys() }; } + + getTrajectoryColorDataIndices(): {node: number[], edge: number[]} { + const connectedEdgesMap = zrUtil.createHashMap(); + const connectedNodesMap = zrUtil.createHashMap(); + const data = this.hostGraph.data; + const getColor = (index: number) => { + const rawData: any = data.getRawDataItem(index); + return rawData?.itemStyle?.color; + }; + const currentLinkColor = getColor(this.node1.dataIndex); + + const sourceNodeColor = getColor(this.node1.dataIndex); + const targetNodeColor = getColor(this.node2.dataIndex); + if (sourceNodeColor === currentLinkColor || targetNodeColor === currentLinkColor) { + connectedEdgesMap.set(this.dataIndex, true); + } + + const sourceNodes = [this.node1]; + const targetNodes = [this.node2]; + + let nodeIteratorIndex = 0; + while (nodeIteratorIndex < sourceNodes.length) { + const sourceNode = sourceNodes[nodeIteratorIndex]; + nodeIteratorIndex++; + + if (getColor(sourceNode.dataIndex) === currentLinkColor) { + connectedNodesMap.set(sourceNode.dataIndex, true); + } + + for (let j = 0; j < sourceNode.inEdges.length; j++) { + const sourceNodeColor = getColor(sourceNode.inEdges[j].node1.dataIndex); + const targetNodeColor = getColor(sourceNode.inEdges[j].node2.dataIndex); + if (sourceNodeColor === currentLinkColor || targetNodeColor === currentLinkColor) { + connectedEdgesMap.set(sourceNode.inEdges[j].dataIndex, true); + } + sourceNodes.push(sourceNode.inEdges[j].node1); + } + } + + nodeIteratorIndex = 0; + while (nodeIteratorIndex < targetNodes.length) { + const targetNode = targetNodes[nodeIteratorIndex]; + nodeIteratorIndex++; + + if (getColor(targetNode.dataIndex) === currentLinkColor) { + connectedNodesMap.set(targetNode.dataIndex, true); + } + + for (let j = 0; j < targetNode.outEdges.length; j++) { + connectedEdgesMap.set(targetNode.outEdges[j].dataIndex, true); + const sourceNodeColor = getColor(targetNode.outEdges[j].node1.dataIndex); + const targetNodeColor = getColor(targetNode.outEdges[j].node2.dataIndex); + if (sourceNodeColor === currentLinkColor || targetNodeColor === currentLinkColor) { + connectedEdgesMap.set(targetNode.outEdges[j].dataIndex, true); + } + targetNodes.push(targetNode.outEdges[j].node2); + } + } + + return { + edge: connectedEdgesMap.keys(), + node: connectedNodesMap.keys() + }; + } } type GetDataName = Host extends GraphEdge ? 'edgeData' : 'data'; diff --git a/test/sankey.html b/test/sankey.html index f9e16bd30e..5d1801b9a5 100644 --- a/test/sankey.html +++ b/test/sankey.html @@ -38,6 +38,7 @@
+
@@ -180,5 +181,136 @@ }); + + \ No newline at end of file