Improve plot color selection

This commit is contained in:
Subhash Halder
2023-07-21 22:42:46 +05:30
parent c38cdcf2b2
commit 6e98759ee7
7 changed files with 59 additions and 30 deletions

View File

@@ -40,7 +40,11 @@
<h1>XY Charts demos</h1>
<pre class="mermaid">
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]
</pre>

View File

@@ -13,8 +13,7 @@ export interface XYChartThemeConfig {
xychartYAxisLableColor: string;
xychartYAxisTitleColor: string;
xychartYAxisTickColor: string;
xychartBarPlotPalette: string[];
xychartLinePlotPalette: string[];
xychartPlotBaseColor: string;
}
export interface ChartComponent {

View File

@@ -1,5 +1,5 @@
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';
export class BarPlot {
@@ -9,7 +9,7 @@ export class BarPlot {
private xAxis: IAxis,
private yAxis: IAxis,
private orientation: XYChartConfig['chartOrientation'],
private chartThemeConfig: XYChartThemeConfig
private plotIndex: number
) {}
getDrawableElement(): DrawableElem[] {
@@ -28,7 +28,7 @@ export class BarPlot {
if (this.orientation === 'horizontal') {
return [
{
groupTexts: ['plot', 'bar-plot'],
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
type: 'rect',
data: finalData.map((data) => ({
x: this.boundingRect.x,
@@ -44,7 +44,7 @@ export class BarPlot {
} else {
return [
{
groupTexts: ['plot', 'bar-plot'],
groupTexts: ['plot', `bar-plot-${this.plotIndex}`],
type: 'rect',
data: finalData.map((data) => ({
x: data[0] - barWidthHalf,

View File

@@ -1,7 +1,7 @@
import { line } from 'd3';
import { DrawableElem, LinePlotData, XYChartThemeConfig } from '../../Interfaces.js';
import { IAxis } from '../axis/index.js';
import { XYChartConfig } from '../../../../../config.type.js';
import { DrawableElem, LinePlotData } from '../../Interfaces.js';
import { IAxis } from '../axis/index.js';
export class LinePlot {
constructor(
@@ -9,7 +9,7 @@ export class LinePlot {
private xAxis: IAxis,
private yAxis: IAxis,
private orientation: XYChartConfig['chartOrientation'],
private chartThemeConfig: XYChartThemeConfig
private plotIndex: number
) {}
getDrawableElement(): DrawableElem[] {
@@ -33,7 +33,7 @@ export class LinePlot {
}
return [
{
groupTexts: ['plot', 'line-plot'],
groupTexts: ['plot', `line-plot-${this.plotIndex}`],
type: 'path',
data: [
{

View File

@@ -62,7 +62,7 @@ export class Plot implements IPlot {
this.chartThemeConfig
).getDrawableElement(),
];
for (const plot of this.chartData.plots) {
for (const [i, plot] of this.chartData.plots.entries()) {
switch (plot.type) {
case 'line':
{
@@ -71,7 +71,7 @@ export class Plot implements IPlot {
this.xAxis,
this.yAxis,
this.chartConfig.chartOrientation,
this.chartThemeConfig
i
);
drawableElem.push(...linePlot.getDrawableElement());
}
@@ -84,7 +84,7 @@ export class Plot implements IPlot {
this.xAxis,
this.yAxis,
this.chartConfig.chartOrientation,
this.chartThemeConfig
i
);
drawableElem.push(...barPlot.getDrawableElement());
}

View File

@@ -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 * as configApi from '../../config.js';
import { sanitizeText } from '../common/common.js';
@@ -27,6 +28,24 @@ const defaultThemeVariables = getThemeVariables();
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 {
return {
xychartTitleColor:
@@ -45,10 +64,8 @@ function getChartDefaultThemeConfig(): XYChartThemeConfig {
config.themeVariables?.xychartYAxisTitleColor || defaultThemeVariables.xychartYAxisTitleColor,
xychartYAxisTickColor:
config.themeVariables?.xychartYAxisTickColor || defaultThemeVariables.xychartYAxisTickColor,
xychartBarPlotPalette:
config.themeVariables?.xychartBarPlotPalette || defaultThemeVariables.xychartBarPlotPalette,
xychartLinePlotPalette:
config.themeVariables?.xychartLinePlotPalette || defaultThemeVariables.xychartLinePlotPalette,
xychartPlotBaseColor:
config.themeVariables?.xychartPlotBaseColor || defaultThemeVariables.xychartPlotBaseColor,
};
}
function getChartDefaultConfig(): XYChartConfig {
@@ -110,6 +127,9 @@ function getChartDefalutData(): XYChartData {
let xyChartConfig: XYChartConfig = getChartDefaultConfig();
let xyChartThemeConfig: XYChartThemeConfig = getChartDefaultThemeConfig();
let xyChartData: XYChartData = getChartDefalutData();
let plotColorPalette = Array.isArray(xyChartThemeConfig.xychartPlotBaseColor)
? xyChartThemeConfig.xychartPlotBaseColor
: plotColorPaletteGenerator(xyChartThemeConfig.xychartPlotBaseColor);
let hasSetXAxis = false;
let hasSetYAxis = false;
@@ -197,27 +217,32 @@ function transformDataWithOutCategory(data: number[]): SimplePlotDataType {
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[]) {
const plotData = transformDataWithOutCategory(data);
xyChartData.plots.push({
type: 'line',
strokeFill:
xyChartThemeConfig.xychartLinePlotPalette[
Math.floor(Math.random() * (xyChartThemeConfig.xychartLinePlotPalette.length - 1))
],
strokeFill: getPlotColorFromPalette(plotIndex),
strokeWidth: 2,
data: plotData,
});
plotIndex++;
}
function setBarData(title: string, data: number[]) {
const plotData = transformDataWithOutCategory(data);
xyChartData.plots.push({
type: 'bar',
fill: xyChartThemeConfig.xychartBarPlotPalette[
Math.floor(Math.random() * (xyChartThemeConfig.xychartBarPlotPalette.length - 1))
],
fill: getPlotColorFromPalette(plotIndex),
data: plotData,
});
plotIndex++;
}
function getDrawableElem(): DrawableElem[] {
@@ -238,9 +263,13 @@ function setWidth(width: number) {
const clear = function () {
commonClear();
plotIndex = 0;
xyChartConfig = getChartDefaultConfig();
xyChartData = getChartDefalutData();
xyChartThemeConfig = getChartDefaultThemeConfig();
plotColorPalette = Array.isArray(xyChartThemeConfig.xychartPlotBaseColor)
? xyChartThemeConfig.xychartPlotBaseColor
: plotColorPaletteGenerator(xyChartThemeConfig.xychartPlotBaseColor);
hasSetXAxis = false;
hasSetYAxis = false;
};

View File

@@ -282,10 +282,7 @@ class Theme {
this.xychartYAxisTitleColor = this.xychartYAxisTitleColor || this.primaryTextColor;
this.xychartYAxisLableColor = this.xychartYAxisLableColor || this.primaryTextColor;
this.xychartYAxisTickColor = this.xychartYAxisTickColor || this.primaryTextColor;
this.xychartBarPlotPalette = this.xychartBarPlotPalette || [this.primaryColor];
this.xychartLinePlotPalette = this.xychartLinePlotPalette || [
adjust(this.primaryColor, { r: -100, g: -100, b: -100 }),
];
this.xychartPlotBaseColor = this.xychartPlotBaseColor || darken(this.primaryColor, 25);
/* requirement-diagram */
this.requirementBackground = this.requirementBackground || this.primaryColor;