|
| 1 | +import type { DataView } from '@visactor/vdataset'; |
| 2 | +import { field, isFunction } from '@visactor/vutils'; |
| 3 | +import { computeNodeValues, computeHierarchicNodeLinks } from '@visactor/vlayouts/es/sankey/hierarchy'; |
| 4 | +import type { SankeyNodeElement } from '@visactor/vlayouts/es/sankey/interface'; |
| 5 | + |
| 6 | +export interface ICompareSankeyLayoutOpt { |
| 7 | + rawData: () => DataView; |
| 8 | + nodeKey: string; |
| 9 | + subNodeGap: number; |
| 10 | +} |
| 11 | + |
| 12 | +export const compareSankeySubData = (data: Array<DataView>, opt: ICompareSankeyLayoutOpt) => { |
| 13 | + const viewData = data[0] as DataView; |
| 14 | + if (!viewData.latestData?.length) { |
| 15 | + return {}; |
| 16 | + } |
| 17 | + // 读取参数 |
| 18 | + const rawDataTree = opt.rawData().latestData[0]; |
| 19 | + const subNodeGap = opt.subNodeGap; |
| 20 | + const keyFunc = isFunction(opt.nodeKey) ? opt.nodeKey : opt.nodeKey ? field(opt.nodeKey as string) : null; |
| 21 | + |
| 22 | + const subNodeMap: { [key: string]: any } = {}; |
| 23 | + rawDataTree.subNode.forEach((sunGroup: any) => { |
| 24 | + subNodeMap[sunGroup.type] = computeHierarchicNodeLinks(sunGroup.nodes, keyFunc); |
| 25 | + computeNodeValues(subNodeMap[sunGroup.type].nodes); |
| 26 | + }); |
| 27 | + const subCount = Object.keys(subNodeMap).length; |
| 28 | + |
| 29 | + const subNodes: any[] = []; |
| 30 | + viewData.latestData[0].nodes.forEach((n: SankeyNodeElement) => { |
| 31 | + let path: (string | number)[] = []; |
| 32 | + if (n.targetLinks.length) { |
| 33 | + const link = n.targetLinks[0]; |
| 34 | + path = [...link.parents]; |
| 35 | + } |
| 36 | + path.push(n.key); |
| 37 | + // 根据path获取sub的节点 |
| 38 | + // 当前已使用比例 |
| 39 | + let currentY = n.y0; |
| 40 | + const totalSize = n.y1 - n.y0 - (subCount - 1) * subNodeGap; |
| 41 | + const totalValue = n.value; |
| 42 | + rawDataTree.subNode.forEach((sunGroup: any) => { |
| 43 | + const subNode = (subNodeMap[sunGroup.type].nodes as SankeyNodeElement[]).find(subN => subN.key === n.key); |
| 44 | + if (!subNode) { |
| 45 | + return; |
| 46 | + } |
| 47 | + const percent = subNode.value / totalValue; |
| 48 | + subNode.x0 = n.x0; |
| 49 | + subNode.x1 = n.x1; |
| 50 | + subNode.y0 = currentY; |
| 51 | + subNode.y1 = currentY + totalSize * percent; |
| 52 | + // @ts-ignore |
| 53 | + subNode.type = sunGroup.type; |
| 54 | + // @ts-ignore |
| 55 | + subNode.sourceNode = n; |
| 56 | + currentY += totalSize * percent + subNodeGap; |
| 57 | + subNodes.push(subNode); |
| 58 | + }); |
| 59 | + }); |
| 60 | + return subNodeMap; |
| 61 | +}; |
0 commit comments