mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
feat: add color blind colors to reviews graph
Signed-off-by: David Brenn <davidbrenn@t-online.de>
This commit is contained in:
parent
8d6d8dc6c8
commit
c530a024e2
3 changed files with 63 additions and 14 deletions
|
@ -22,7 +22,7 @@ import {
|
|||
sum,
|
||||
} from "d3";
|
||||
|
||||
import type { GraphBounds } from "./graph-helpers";
|
||||
import { colorBlindColors, type GraphBounds } from "./graph-helpers";
|
||||
|
||||
type Count = [string, number, boolean, string];
|
||||
export interface GraphData {
|
||||
|
@ -36,13 +36,13 @@ let barColours;
|
|||
if((window as any).colorBlindMode)
|
||||
{
|
||||
barColours = [
|
||||
"#88CCEE", /* new */
|
||||
"#44AA99", /* learn */
|
||||
"#117733", /* relearn */
|
||||
"#CC6677", /* young */
|
||||
"#882255", /* mature */
|
||||
"#DDCC77", /* suspended */
|
||||
"#332288", /* buried */
|
||||
colorBlindColors.new, /* new */
|
||||
colorBlindColors.learn, /* learn */
|
||||
colorBlindColors.relearn, /* relearn */
|
||||
colorBlindColors.young, /* young */
|
||||
colorBlindColors.mature, /* mature */
|
||||
colorBlindColors.suspended, /* suspended */
|
||||
colorBlindColors.buried, /* buried */
|
||||
];
|
||||
}
|
||||
else
|
||||
|
|
|
@ -105,3 +105,17 @@ export function numericMap<T>(obj: { [k: string]: T }): Map<number, T> {
|
|||
export function getNumericMapBinValue(d: Bin<Map<number, number>, number>): number {
|
||||
return sum(d, (d) => d[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Colorblind-friendly colors from https://davidmathlogic.com/colorblind/
|
||||
*/
|
||||
export const colorBlindColors = {
|
||||
new: "#88CCEE",
|
||||
learn: "#44AA99",
|
||||
relearn: "#117733",
|
||||
young: "#CC6677",
|
||||
mature: "#882255",
|
||||
suspended: "#DDCC77",
|
||||
buried: "#332288",
|
||||
filtered: "#AA4499"
|
||||
};
|
||||
|
|
|
@ -22,16 +22,20 @@ import {
|
|||
interpolateGreens,
|
||||
interpolatePurples,
|
||||
interpolateReds,
|
||||
interpolateRgb,
|
||||
max,
|
||||
min,
|
||||
pointer,
|
||||
scaleLinear,
|
||||
scaleOrdinal,
|
||||
scaleSequential,
|
||||
select,
|
||||
sum,
|
||||
color,
|
||||
hsl
|
||||
} from "d3";
|
||||
|
||||
import type { GraphBounds, TableDatum } from "./graph-helpers";
|
||||
import { colorBlindColors, type GraphBounds, type TableDatum } from "./graph-helpers";
|
||||
import { GraphRange, numericMap, setDataAvailable } from "./graph-helpers";
|
||||
import { hideTooltip, showTooltip } from "./tooltip-utils.svelte";
|
||||
|
||||
|
@ -188,21 +192,52 @@ export function renderReviews(
|
|||
x.domain() as any,
|
||||
);
|
||||
|
||||
const colorBlindMode = (window as any).colorBlindMode;
|
||||
|
||||
|
||||
function makeColorBlindGradient(baseHex: string, satAdjust = 0.02, lightAdjust = 0.02) {
|
||||
const base = color(baseHex);
|
||||
if (!base) throw new Error(`Invalid color: ${baseHex}`);
|
||||
|
||||
const lighter = hsl(base);
|
||||
lighter.s = Math.min(1, lighter.s + satAdjust);
|
||||
lighter.l = Math.min(1, lighter.l + lightAdjust);
|
||||
|
||||
const darker = hsl(base);
|
||||
darker.s = Math.max(0, darker.s - satAdjust);
|
||||
darker.l = Math.max(0, darker.l - lightAdjust);
|
||||
|
||||
return scaleSequential(interpolateRgb(darker.toString(), lighter.toString()));
|
||||
}
|
||||
|
||||
const colorBlindScales = {
|
||||
mature: makeColorBlindGradient(colorBlindColors.mature),
|
||||
learn: makeColorBlindGradient(colorBlindColors.learn),
|
||||
relearn: makeColorBlindGradient(colorBlindColors.relearn),
|
||||
young: makeColorBlindGradient(colorBlindColors.young),
|
||||
suspended: makeColorBlindGradient(colorBlindColors.suspended),
|
||||
buried: makeColorBlindGradient(colorBlindColors.buried),
|
||||
filtered: makeColorBlindGradient(colorBlindColors.filtered)
|
||||
};
|
||||
|
||||
Object.values(colorBlindScales).forEach(scale => scale.domain(x.domain() as any));
|
||||
|
||||
function binColor(idx: BinIndex): ScaleSequential<string> {
|
||||
switch (idx) {
|
||||
case BinIndex.Mature:
|
||||
return darkerGreens;
|
||||
return colorBlindMode ? colorBlindScales.mature : darkerGreens;
|
||||
case BinIndex.Young:
|
||||
return lighterGreens;
|
||||
return colorBlindMode ? colorBlindScales.young : lighterGreens;
|
||||
case BinIndex.Learn:
|
||||
return blues;
|
||||
return colorBlindMode ? colorBlindScales.learn : blues;
|
||||
case BinIndex.Relearn:
|
||||
return reds;
|
||||
return colorBlindMode ? colorBlindScales.relearn : reds;
|
||||
case BinIndex.Filtered:
|
||||
return purples;
|
||||
return colorBlindMode ? colorBlindScales.filtered : purples;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function valueLabel(n: number): string {
|
||||
if (showTime) {
|
||||
return timeSpan(n / 1000, false, true, TimespanUnit.Hours);
|
||||
|
|
Loading…
Reference in a new issue