From b23e86aea39c4e1afa0582fd2788550533ebd6a2 Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Sun, 25 Jun 2023 00:22:36 +0300 Subject: [PATCH] Added options for coloring --- demos/sankey.html | 6 ++ packages/mermaid/src/config.type.ts | 12 ++- packages/mermaid/src/defaultConfig.ts | 5 ++ .../mermaid/src/diagrams/sankey/sankeyDB.ts | 2 +- .../src/diagrams/sankey/sankeyRenderer.ts | 73 ++++++++++++------- .../src/diagrams/sankey/sankeyUtils.ts | 2 +- 6 files changed, 72 insertions(+), 28 deletions(-) diff --git a/demos/sankey.html b/demos/sankey.html index 8429218b5..3dc7a2332 100644 --- a/demos/sankey.html +++ b/demos/sankey.html @@ -98,6 +98,12 @@ flowchart: { curve: 'basis' }, gantt: { axisFormat: '%m/%d/%Y' }, sequence: { actorMargin: 50 }, + sankey: { + title: 'Hey, this is Sankey-Beta', + width: 1200, + height: 600, + linkColor: 'gradient', + }, }); diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index f50a15d6b..7e0b67eb5 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -412,7 +412,17 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig { wrappingWidth?: number; } -export type SankeyDiagramConfig = BaseDiagramConfig; +export enum SankeyLinkColor { + source = 'source', + target = 'target', + gradient = 'gradient', +} + +export interface SankeyDiagramConfig extends BaseDiagramConfig { + width?: number; + height?: number; + linkColor?: SankeyLinkColor | string; +} export interface FontConfig { fontSize?: string | number; diff --git a/packages/mermaid/src/defaultConfig.ts b/packages/mermaid/src/defaultConfig.ts index c9407828f..4ece25010 100644 --- a/packages/mermaid/src/defaultConfig.ts +++ b/packages/mermaid/src/defaultConfig.ts @@ -2270,6 +2270,11 @@ const config: Partial = { padding: 10, maxNodeWidth: 200, }, + sankey: { + width: 800, + height: 400, + linkColor: 'gradient', + }, fontSize: 16, }; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyDB.ts b/packages/mermaid/src/diagrams/sankey/sankeyDB.ts index 04515cda4..098f3938c 100644 --- a/packages/mermaid/src/diagrams/sankey/sankeyDB.ts +++ b/packages/mermaid/src/diagrams/sankey/sankeyDB.ts @@ -20,7 +20,7 @@ let nodesMap: Record = {}; let nodeAlign = 'justify'; const setNodeAlign = (alignment: string): void => { - const nodeAlignments: Set= new Set(['left', 'right', 'center', 'justify']); + const nodeAlignments: Set = new Set(['left', 'right', 'center', 'justify']); if (nodeAlignments.has(alignment)) { nodeAlign = alignment; } diff --git a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts index 1a8eb5c7e..dd31e775e 100644 --- a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts +++ b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts @@ -20,9 +20,10 @@ import { } from 'd3-sankey'; import { configureSvgSize } from '../../setupGraphViewbox.js'; import { Uid } from './sankeyUtils.js'; +import { SankeyLinkColor } from '../../config.type.js'; /** - * Draws a sequenceDiagram in the tag with id: id based on the graph definition in text. + * Draws Sankey diagram. * * @param text - The text of the diagram * @param id - The id of the diagram which will be used as a DOM element id¨ @@ -30,10 +31,14 @@ import { Uid } from './sankeyUtils.js'; * @param diagObj - A standard diagram containing the db and the text and type etc of the diagram */ export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void { - // TODO: Figure out what is happening there + // Get Sankey config + const { securityLevel, sankey: conf } = configApi.getConfig(); + + // TODO: + // This code repeats for every diagram + // Figure out what is happening there, probably it should be separated // The main thing is svg object that is a d3 wrapper for svg operations // - const { securityLevel, sequence: conf } = configApi.getConfig(); let sandboxElement: any; if (securityLevel === 'sandbox') { sandboxElement = d3select('#i' + id); @@ -43,18 +48,17 @@ export const draw = function (text: string, id: string, _version: string, diagOb if (securityLevel === 'sandbox' && sandboxElement) { root = d3select(sandboxElement.nodes()[0].contentDocument.body); } - const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`); // Establish svg dimensions and get width and height // - const elem = doc.getElementById(id); - const width = elem.parentElement.offsetWidth; - const height = 600; + const width = conf?.width || 800; + const height = conf?.height || 400; + const useMaxWidth = conf?.useMaxWidth || false; - // FIX: using max width prevents height from being set - configureSvgSize(svg, height, width, false); - // svg.attr('height', height); // that's why we need this line + // FIX: using max width prevents height from being set, is it intended? + // to add height directly one can use `svg.attr('height', height)` + configureSvgSize(svg, height, width, useMaxWidth); // Prepare data for construction based on diagObj.db // This must be a mutable object with `nodes` and `links` properties: @@ -142,27 +146,46 @@ export const draw = function (text: string, id: string, _version: string, diagOb .attr('class', 'link') .style('mix-blend-mode', 'multiply'); - const gradient = link - .append('linearGradient') - .attr('id', (d) => (d.uid = Uid.next('linearGradient-')).id) - .attr('gradientUnits', 'userSpaceOnUse') - .attr('x1', (d) => d.source.x1) - .attr('x2', (d) => d.target.x0); + const linkColor = conf?.linkColor || SankeyLinkColor.gradient; - gradient - .append('stop') - .attr('offset', '0%') - .attr('stop-color', (d) => colorScheme(d.source.id)); + if (linkColor === SankeyLinkColor.gradient) { + const gradient = link + .append('linearGradient') + .attr('id', (d) => (d.uid = Uid.next('linearGradient-')).id) + .attr('gradientUnits', 'userSpaceOnUse') + .attr('x1', (d) => d.source.x1) + .attr('x2', (d) => d.target.x0); - gradient - .append('stop') - .attr('offset', '100%') - .attr('stop-color', (d) => colorScheme(d.target.id)); + gradient + .append('stop') + .attr('offset', '0%') + .attr('stop-color', (d) => colorScheme(d.source.id)); + + gradient + .append('stop') + .attr('offset', '100%') + .attr('stop-color', (d) => colorScheme(d.target.id)); + } + + let coloring: any; + switch (linkColor) { + case SankeyLinkColor.gradient: + coloring = (d) => d.uid; + break; + case SankeyLinkColor.source: + coloring = (d) => d.source.id; + break; + case SankeyLinkColor.target: + coloring = (d) => d.target.id; + break; + default: + coloring = linkColor; + } link .append('path') .attr('d', d3SankeyLinkHorizontal()) - .attr('stroke', (d: any) => d.uid) + .attr('stroke', coloring) .attr('stroke-width', (d: any) => Math.max(1, d.width)); }; diff --git a/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts b/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts index d88e528c5..08e4c547f 100644 --- a/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts +++ b/packages/mermaid/src/diagrams/sankey/sankeyUtils.ts @@ -24,4 +24,4 @@ export class Uid { toString(): string { return 'url(' + this.href + ')'; } -} \ No newline at end of file +}