mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-11 10:09:39 +02:00
Improve plot color selection
This commit is contained in:
@@ -40,7 +40,11 @@
|
|||||||
<h1>XY Charts demos</h1>
|
<h1>XY Charts demos</h1>
|
||||||
<pre class="mermaid">
|
<pre class="mermaid">
|
||||||
xychart-beta
|
xychart-beta
|
||||||
line [23, 46, 75, 43]
|
line [23, 46, 77, 34]
|
||||||
|
line [45, 32, 33, 12]
|
||||||
|
line [87, 54, 99, 85]
|
||||||
|
line [78, 88, 22, 4]
|
||||||
|
line [22, 29, 75, 33]
|
||||||
bar "sample bat" [52, 96, 35, 10]
|
bar "sample bat" [52, 96, 35, 10]
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@@ -13,8 +13,7 @@ export interface XYChartThemeConfig {
|
|||||||
xychartYAxisLableColor: string;
|
xychartYAxisLableColor: string;
|
||||||
xychartYAxisTitleColor: string;
|
xychartYAxisTitleColor: string;
|
||||||
xychartYAxisTickColor: string;
|
xychartYAxisTickColor: string;
|
||||||
xychartBarPlotPalette: string[];
|
xychartPlotBaseColor: string;
|
||||||
xychartLinePlotPalette: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ChartComponent {
|
export interface ChartComponent {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { XYChartConfig } from '../../../../../config.type.js';
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
import { BarPlotData, BoundingRect, DrawableElem, XYChartThemeConfig } from '../../Interfaces.js';
|
import { BarPlotData, BoundingRect, DrawableElem } from '../../Interfaces.js';
|
||||||
import { IAxis } from '../axis/index.js';
|
import { IAxis } from '../axis/index.js';
|
||||||
|
|
||||||
export class BarPlot {
|
export class BarPlot {
|
||||||
@@ -9,7 +9,7 @@ export class BarPlot {
|
|||||||
private xAxis: IAxis,
|
private xAxis: IAxis,
|
||||||
private yAxis: IAxis,
|
private yAxis: IAxis,
|
||||||
private orientation: XYChartConfig['chartOrientation'],
|
private orientation: XYChartConfig['chartOrientation'],
|
||||||
private chartThemeConfig: XYChartThemeConfig
|
private plotIndex: number
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
@@ -28,7 +28,7 @@ export class BarPlot {
|
|||||||
if (this.orientation === 'horizontal') {
|
if (this.orientation === 'horizontal') {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', 'bar-plot'],
|
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
data: finalData.map((data) => ({
|
data: finalData.map((data) => ({
|
||||||
x: this.boundingRect.x,
|
x: this.boundingRect.x,
|
||||||
@@ -44,7 +44,7 @@ export class BarPlot {
|
|||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', 'bar-plot'],
|
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
|
||||||
type: 'rect',
|
type: 'rect',
|
||||||
data: finalData.map((data) => ({
|
data: finalData.map((data) => ({
|
||||||
x: data[0] - barWidthHalf,
|
x: data[0] - barWidthHalf,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { line } from 'd3';
|
import { line } from 'd3';
|
||||||
import { DrawableElem, LinePlotData, XYChartThemeConfig } from '../../Interfaces.js';
|
|
||||||
import { IAxis } from '../axis/index.js';
|
|
||||||
import { XYChartConfig } from '../../../../../config.type.js';
|
import { XYChartConfig } from '../../../../../config.type.js';
|
||||||
|
import { DrawableElem, LinePlotData } from '../../Interfaces.js';
|
||||||
|
import { IAxis } from '../axis/index.js';
|
||||||
|
|
||||||
export class LinePlot {
|
export class LinePlot {
|
||||||
constructor(
|
constructor(
|
||||||
@@ -9,7 +9,7 @@ export class LinePlot {
|
|||||||
private xAxis: IAxis,
|
private xAxis: IAxis,
|
||||||
private yAxis: IAxis,
|
private yAxis: IAxis,
|
||||||
private orientation: XYChartConfig['chartOrientation'],
|
private orientation: XYChartConfig['chartOrientation'],
|
||||||
private chartThemeConfig: XYChartThemeConfig
|
private plotIndex: number
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
getDrawableElement(): DrawableElem[] {
|
getDrawableElement(): DrawableElem[] {
|
||||||
@@ -33,7 +33,7 @@ export class LinePlot {
|
|||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
groupTexts: ['plot', 'line-plot'],
|
groupTexts: ['plot', `line-plot-${this.plotIndex}`],
|
||||||
type: 'path',
|
type: 'path',
|
||||||
data: [
|
data: [
|
||||||
{
|
{
|
||||||
|
@@ -62,7 +62,7 @@ export class Plot implements IPlot {
|
|||||||
this.chartThemeConfig
|
this.chartThemeConfig
|
||||||
).getDrawableElement(),
|
).getDrawableElement(),
|
||||||
];
|
];
|
||||||
for (const plot of this.chartData.plots) {
|
for (const [i, plot] of this.chartData.plots.entries()) {
|
||||||
switch (plot.type) {
|
switch (plot.type) {
|
||||||
case 'line':
|
case 'line':
|
||||||
{
|
{
|
||||||
@@ -71,7 +71,7 @@ export class Plot implements IPlot {
|
|||||||
this.xAxis,
|
this.xAxis,
|
||||||
this.yAxis,
|
this.yAxis,
|
||||||
this.chartConfig.chartOrientation,
|
this.chartConfig.chartOrientation,
|
||||||
this.chartThemeConfig
|
i
|
||||||
);
|
);
|
||||||
drawableElem.push(...linePlot.getDrawableElement());
|
drawableElem.push(...linePlot.getDrawableElement());
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ export class Plot implements IPlot {
|
|||||||
this.xAxis,
|
this.xAxis,
|
||||||
this.yAxis,
|
this.yAxis,
|
||||||
this.chartConfig.chartOrientation,
|
this.chartConfig.chartOrientation,
|
||||||
this.chartThemeConfig
|
i
|
||||||
);
|
);
|
||||||
drawableElem.push(...barPlot.getDrawableElement());
|
drawableElem.push(...barPlot.getDrawableElement());
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { log } from '../../logger.js';
|
// @ts-ignore: TODO Fix ts errors
|
||||||
|
import { adjust, channel, toHsla, isDark, lighten, darken } from 'khroma';
|
||||||
import mermaidAPI from '../../mermaidAPI.js';
|
import mermaidAPI from '../../mermaidAPI.js';
|
||||||
import * as configApi from '../../config.js';
|
import * as configApi from '../../config.js';
|
||||||
import { sanitizeText } from '../common/common.js';
|
import { sanitizeText } from '../common/common.js';
|
||||||
@@ -27,6 +28,24 @@ const defaultThemeVariables = getThemeVariables();
|
|||||||
|
|
||||||
const config = configApi.getConfig();
|
const config = configApi.getConfig();
|
||||||
|
|
||||||
|
function plotColorPaletteGenerator(baseColor: string, noOfColorNeeded = 15): string[] {
|
||||||
|
const colors = [];
|
||||||
|
const MAX_HUE_VALUE = 360;
|
||||||
|
const baseHue = channel(baseColor, 'h');
|
||||||
|
if (baseHue > MAX_HUE_VALUE / 2) {
|
||||||
|
const decr = Math.floor(baseHue / noOfColorNeeded);
|
||||||
|
for (let i = 0; i <= baseHue; i += decr) {
|
||||||
|
colors.push(adjust(baseColor, { h: -i }));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const incr = Math.floor((MAX_HUE_VALUE - baseHue) / noOfColorNeeded);
|
||||||
|
for (let i = 0; i <= baseHue; i += incr) {
|
||||||
|
colors.push(adjust(baseColor, { h: i }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return colors;
|
||||||
|
}
|
||||||
|
|
||||||
function getChartDefaultThemeConfig(): XYChartThemeConfig {
|
function getChartDefaultThemeConfig(): XYChartThemeConfig {
|
||||||
return {
|
return {
|
||||||
xychartTitleColor:
|
xychartTitleColor:
|
||||||
@@ -45,10 +64,8 @@ function getChartDefaultThemeConfig(): XYChartThemeConfig {
|
|||||||
config.themeVariables?.xychartYAxisTitleColor || defaultThemeVariables.xychartYAxisTitleColor,
|
config.themeVariables?.xychartYAxisTitleColor || defaultThemeVariables.xychartYAxisTitleColor,
|
||||||
xychartYAxisTickColor:
|
xychartYAxisTickColor:
|
||||||
config.themeVariables?.xychartYAxisTickColor || defaultThemeVariables.xychartYAxisTickColor,
|
config.themeVariables?.xychartYAxisTickColor || defaultThemeVariables.xychartYAxisTickColor,
|
||||||
xychartBarPlotPalette:
|
xychartPlotBaseColor:
|
||||||
config.themeVariables?.xychartBarPlotPalette || defaultThemeVariables.xychartBarPlotPalette,
|
config.themeVariables?.xychartPlotBaseColor || defaultThemeVariables.xychartPlotBaseColor,
|
||||||
xychartLinePlotPalette:
|
|
||||||
config.themeVariables?.xychartLinePlotPalette || defaultThemeVariables.xychartLinePlotPalette,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
function getChartDefaultConfig(): XYChartConfig {
|
function getChartDefaultConfig(): XYChartConfig {
|
||||||
@@ -110,6 +127,9 @@ function getChartDefalutData(): XYChartData {
|
|||||||
let xyChartConfig: XYChartConfig = getChartDefaultConfig();
|
let xyChartConfig: XYChartConfig = getChartDefaultConfig();
|
||||||
let xyChartThemeConfig: XYChartThemeConfig = getChartDefaultThemeConfig();
|
let xyChartThemeConfig: XYChartThemeConfig = getChartDefaultThemeConfig();
|
||||||
let xyChartData: XYChartData = getChartDefalutData();
|
let xyChartData: XYChartData = getChartDefalutData();
|
||||||
|
let plotColorPalette = Array.isArray(xyChartThemeConfig.xychartPlotBaseColor)
|
||||||
|
? xyChartThemeConfig.xychartPlotBaseColor
|
||||||
|
: plotColorPaletteGenerator(xyChartThemeConfig.xychartPlotBaseColor);
|
||||||
let hasSetXAxis = false;
|
let hasSetXAxis = false;
|
||||||
let hasSetYAxis = false;
|
let hasSetYAxis = false;
|
||||||
|
|
||||||
@@ -197,27 +217,32 @@ function transformDataWithOutCategory(data: number[]): SimplePlotDataType {
|
|||||||
|
|
||||||
return retData;
|
return retData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let plotIndex = 0;
|
||||||
|
|
||||||
|
function getPlotColorFromPalette(plotIndex: number): string {
|
||||||
|
return plotColorPalette[plotIndex === 0 ? 0 : plotIndex % (plotColorPalette.length - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
function setLineData(title: string, data: number[]) {
|
function setLineData(title: string, data: number[]) {
|
||||||
const plotData = transformDataWithOutCategory(data);
|
const plotData = transformDataWithOutCategory(data);
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: 'line',
|
type: 'line',
|
||||||
strokeFill:
|
strokeFill: getPlotColorFromPalette(plotIndex),
|
||||||
xyChartThemeConfig.xychartLinePlotPalette[
|
|
||||||
Math.floor(Math.random() * (xyChartThemeConfig.xychartLinePlotPalette.length - 1))
|
|
||||||
],
|
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
data: plotData,
|
data: plotData,
|
||||||
});
|
});
|
||||||
|
plotIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setBarData(title: string, data: number[]) {
|
function setBarData(title: string, data: number[]) {
|
||||||
const plotData = transformDataWithOutCategory(data);
|
const plotData = transformDataWithOutCategory(data);
|
||||||
xyChartData.plots.push({
|
xyChartData.plots.push({
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
fill: xyChartThemeConfig.xychartBarPlotPalette[
|
fill: getPlotColorFromPalette(plotIndex),
|
||||||
Math.floor(Math.random() * (xyChartThemeConfig.xychartBarPlotPalette.length - 1))
|
|
||||||
],
|
|
||||||
data: plotData,
|
data: plotData,
|
||||||
});
|
});
|
||||||
|
plotIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDrawableElem(): DrawableElem[] {
|
function getDrawableElem(): DrawableElem[] {
|
||||||
@@ -238,9 +263,13 @@ function setWidth(width: number) {
|
|||||||
|
|
||||||
const clear = function () {
|
const clear = function () {
|
||||||
commonClear();
|
commonClear();
|
||||||
|
plotIndex = 0;
|
||||||
xyChartConfig = getChartDefaultConfig();
|
xyChartConfig = getChartDefaultConfig();
|
||||||
xyChartData = getChartDefalutData();
|
xyChartData = getChartDefalutData();
|
||||||
xyChartThemeConfig = getChartDefaultThemeConfig();
|
xyChartThemeConfig = getChartDefaultThemeConfig();
|
||||||
|
plotColorPalette = Array.isArray(xyChartThemeConfig.xychartPlotBaseColor)
|
||||||
|
? xyChartThemeConfig.xychartPlotBaseColor
|
||||||
|
: plotColorPaletteGenerator(xyChartThemeConfig.xychartPlotBaseColor);
|
||||||
hasSetXAxis = false;
|
hasSetXAxis = false;
|
||||||
hasSetYAxis = false;
|
hasSetYAxis = false;
|
||||||
};
|
};
|
||||||
|
@@ -282,10 +282,7 @@ class Theme {
|
|||||||
this.xychartYAxisTitleColor = this.xychartYAxisTitleColor || this.primaryTextColor;
|
this.xychartYAxisTitleColor = this.xychartYAxisTitleColor || this.primaryTextColor;
|
||||||
this.xychartYAxisLableColor = this.xychartYAxisLableColor || this.primaryTextColor;
|
this.xychartYAxisLableColor = this.xychartYAxisLableColor || this.primaryTextColor;
|
||||||
this.xychartYAxisTickColor = this.xychartYAxisTickColor || this.primaryTextColor;
|
this.xychartYAxisTickColor = this.xychartYAxisTickColor || this.primaryTextColor;
|
||||||
this.xychartBarPlotPalette = this.xychartBarPlotPalette || [this.primaryColor];
|
this.xychartPlotBaseColor = this.xychartPlotBaseColor || darken(this.primaryColor, 25);
|
||||||
this.xychartLinePlotPalette = this.xychartLinePlotPalette || [
|
|
||||||
adjust(this.primaryColor, { r: -100, g: -100, b: -100 }),
|
|
||||||
];
|
|
||||||
|
|
||||||
/* requirement-diagram */
|
/* requirement-diagram */
|
||||||
this.requirementBackground = this.requirementBackground || this.primaryColor;
|
this.requirementBackground = this.requirementBackground || this.primaryColor;
|
||||||
|
Reference in New Issue
Block a user