colorblind friendly colors for card ease, card counts, and card intervals

This commit is contained in:
OblivionSword 2025-08-11 16:04:21 +02:00
parent 8b99a550cd
commit 13ea189be0
3 changed files with 54 additions and 9 deletions

View file

@ -18,6 +18,8 @@ import {
schemeGreens, schemeGreens,
schemeOranges, schemeOranges,
schemeReds, schemeReds,
schemePurples,
schemeBuPu,
select, select,
sum, sum,
} from "d3"; } from "d3";
@ -31,15 +33,32 @@ export interface GraphData {
totalCards: string; totalCards: string;
} }
const barColours = [ let barColours;
if((window as any).colorBlindMode)
{
barColours = [
schemeBlues[5][2], /* new */
schemeOranges[5][2], /* learn */
schemeReds[5][2], /* relearn */
schemePurples[7][4], /* young */
schemeBuPu[8][6], /* mature */
"#00FF60", /* suspended */
"#1F1F1F", /* buried */
];
}
else
{
barColours = [
schemeBlues[5][2], /* new */ schemeBlues[5][2], /* new */
schemeOranges[5][2], /* learn */ schemeOranges[5][2], /* learn */
schemeReds[5][2], /* relearn */ schemeReds[5][2], /* relearn */
schemeGreens[5][2], /* young */ schemeGreens[5][2], /* young */
schemeGreens[5][3], /* mature */ schemeGreens[5][3], /* mature */
"#FFDC41", /* suspended */ "#FFDC41", /* suspended */
"grey", /* buried */ "#grey", /* buried */
]; ];
}
function countCards(data: GraphsResponse, separateInactive: boolean): Count[] { function countCards(data: GraphsResponse, separateInactive: boolean): Count[] {
const countData = separateInactive ? data.cardCounts!.excludingInactive! : data.cardCounts!.includingInactive!; const countData = separateInactive ? data.cardCounts!.excludingInactive! : data.cardCounts!.includingInactive!;

View file

@ -8,8 +8,8 @@
import type { GraphsResponse } from "@generated/anki/stats_pb"; import type { GraphsResponse } from "@generated/anki/stats_pb";
import * as tr from "@generated/ftl"; import * as tr from "@generated/ftl";
import { localizedNumber } from "@tslib/i18n"; import { localizedNumber } from "@tslib/i18n";
import type { Bin, ScaleLinear } from "d3"; import type { Bin, ScaleLinear, ScaleSequential } from "d3";
import { bin, extent, interpolateRdYlGn, scaleLinear, scaleSequential, sum } from "d3"; import { bin, extent, interpolateRdYlGn, interpolateTurbo, scaleLinear, scaleSequential, sum } from "d3";
import type { SearchDispatch, TableDatum } from "./graph-helpers"; import type { SearchDispatch, TableDatum } from "./graph-helpers";
import { getNumericMapBinValue, numericMap } from "./graph-helpers"; import { getNumericMapBinValue, numericMap } from "./graph-helpers";
@ -84,7 +84,17 @@ export function prepareData(
.thresholds(ticks)(allEases.entries() as any); .thresholds(ticks)(allEases.entries() as any);
const total = sum(bins as any, getNumericMapBinValue); const total = sum(bins as any, getNumericMapBinValue);
const colourScale = scaleSequential(interpolateRdYlGn).domain([xMin, 300]);
let colourScale;
if ((window as any).colorBlindMode)
{
colourScale = scaleSequential(interpolateTurbo).domain([xMin, 300]);
}
else
{
colourScale = scaleSequential(interpolateRdYlGn).domain([xMin, 300]);
}
function hoverText(bin: Bin<number, number>, _percent: number): string { function hoverText(bin: Bin<number, number>, _percent: number): string {
const minPct = Math.floor(bin.x0!); const minPct = Math.floor(bin.x0!);

View file

@ -10,7 +10,7 @@ import * as tr from "@generated/ftl";
import { localizedNumber } from "@tslib/i18n"; import { localizedNumber } from "@tslib/i18n";
import { timeSpan } from "@tslib/time"; import { timeSpan } from "@tslib/time";
import type { Bin } from "d3"; import type { Bin } from "d3";
import { bin, extent, interpolateBlues, quantile, scaleLinear, scaleSequential, sum } from "d3"; import { bin, extent, interpolateBlues, interpolateCividis, quantile, scaleLinear, scaleSequential, sum } from "d3";
import type { SearchDispatch, TableDatum } from "./graph-helpers"; import type { SearchDispatch, TableDatum } from "./graph-helpers";
import { numericMap } from "./graph-helpers"; import { numericMap } from "./graph-helpers";
@ -147,8 +147,24 @@ export function prepareIntervalData(
return [null, []]; return [null, []];
} }
const adjustedRange = scaleLinear().range([0.7, 0.3]); let adjustedRange;
const colourScale = scaleSequential((n) => interpolateBlues(adjustedRange(n)!)).domain([xMax!, xMin!]); let colourScale;
if ((window as any).colorBlindMode)
{
adjustedRange = scaleLinear().range([0.1, 1.0]);
colourScale = scaleSequential((n) => interpolateCividis(adjustedRange(n)!)).domain([xMax!, xMin!]);
}
else
{
adjustedRange = scaleLinear().range([0.7, 0.3]);
colourScale = scaleSequential((n) => interpolateBlues(adjustedRange(n)!)).domain([xMax!, xMin!]);
}
//const adjustedRange = scaleLinear().range([0.7, 0.3]);
//const adjustedRange = scaleLinear().range([0.1, 1.0]);
//const colourScale = scaleSequential((n) => interpolateBlues(adjustedRange(n)!)).domain([xMax!, xMin!]);
//const colourScale = scaleSequential((n) => interpolateCividis(adjustedRange(n)!)).domain([xMax!, xMin!]);
function hoverText( function hoverText(
bin: Bin<number, number>, bin: Bin<number, number>,