UNPKG

@ant-design/graphs

Version:
112 lines (99 loc) 4.12 kB
import type { BaseTransformOptions, DrawData, EdgeData, ID, RuntimeContext } from '@antv/g6'; import { BaseTransform, idOf } from '@antv/g6'; import { linear, log, pow, sqrt } from '../utils/scale'; export interface MapEdgeLineWidthOptions extends BaseTransformOptions { /** * 数值 */ value: number | ((data: EdgeData) => number); /** * 最小值 */ minValue?: number | ((data: EdgeData, edges: Record<ID, number>) => number); /** * 最大值 */ maxValue?: number | ((data: EdgeData, edges: Record<ID, number>) => number); /** * 最小线宽 */ minLineWidth?: number | ((data: EdgeData) => number); /** * 最大线宽 */ maxLineWidth?: number | ((data: EdgeData) => number); /** * 插值函数,用于将数值映射到线宽 * - `'linear'`:线性插值函数,将一个值从一个范围线性映射到另一个范围,常用于处理中心性值的差异较小的情况 * - `'log'`:对数插值函数,将一个值从一个范围对数映射到另一个范围,常用于处理中心性值的差异较大的情况 * - `'pow'`:幂律插值函数,将一个值从一个范围幂律映射到另一个范围,常用于处理中心性值的差异较大的情况 * - `'sqrt'`:平方根插值函数,将一个值从一个范围平方根映射到另一个范围,常用于处理中心性值的差异较大的情况 * - 自定义插值函数:`(value: number, domain: [number, number], range: [number, number]) => number`,其中 `value` 为需要映射的值,`domain` 为输入值的范围,`range` 为输出值的范围 */ scale?: | 'linear' | 'log' | 'pow' | 'sqrt' | ((value: number, domain: [number, number], range: [number, number]) => number); } export class MapEdgeLineWidth extends BaseTransform { static defaultOptions: Partial<MapEdgeLineWidthOptions> = { minValue: (edge, edges) => Math.min(...Object.values(edges)), maxValue: (edge, edges) => Math.max(...Object.values(edges)), minLineWidth: 1, maxLineWidth: 10, scale: 'linear', }; constructor(context: RuntimeContext, options: MapEdgeLineWidthOptions) { super(context, Object.assign({}, MapEdgeLineWidth.defaultOptions, options)); } beforeDraw(input: DrawData): DrawData { const { maxValue, minValue, maxLineWidth, minLineWidth, scale, value } = this.options; const edges = this.context.model.getEdgeData(); const valueFunc = typeof value === 'function' ? value : () => value; const values = Object.fromEntries(edges.map((edge) => [idOf(edge), valueFunc(edge)])); const { add: { edges: edgesToAdd }, update: { edges: edgesToUpdate }, } = input; [...edgesToAdd.values(), ...edgesToUpdate.values()].forEach((edge) => { const lineWidth = this.assignLineWidthByValue( values[idOf(edge)] || 0, typeof minValue === 'function' ? minValue(edge, values) : minValue, typeof maxValue === 'function' ? maxValue(edge, values) : maxValue, typeof minLineWidth === 'function' ? minLineWidth(edge) : minLineWidth, typeof maxLineWidth === 'function' ? maxLineWidth(edge) : maxLineWidth, scale, ); edge.style ||= {}; edge.style.lineWidth = lineWidth; }); return input; } private assignLineWidthByValue = ( value: number, minValue: number, maxValue: number, minLineWidth: number, maxLineWidth: number, scale: MapEdgeLineWidthOptions['scale'], ): number => { const domain: [number, number] = [minValue, maxValue]; const range: [number, number] = [minLineWidth, maxLineWidth]; if (value < minValue || value > maxValue || minValue === maxValue) return range[0]; if (typeof scale === 'function') return scale(value, domain, range); switch (scale) { case 'linear': return linear(value, domain, range); case 'log': return log(value, domain, range); case 'pow': return pow(value, domain, range, 2); case 'sqrt': return sqrt(value, domain, range); default: return range[0]; } }; }