Skip to content

Commit

Permalink
draft of diverging order checks
Browse files Browse the repository at this point in the history
  • Loading branch information
mcnuttandrew committed Jan 10, 2024
1 parent 1376926 commit b402c66
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 139 deletions.
65 changes: 29 additions & 36 deletions src/components/ColorScatterPlot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@
label: zScale.domain()[1].toFixed(1),
},
};
$: axisColor = bg.toChroma().luminance() > 0.5 ? "gray" : "white";
$: axisColor = bg.luminance() > 0.5 ? "gray" : "white";
let hoveredPoint: Color | false = false;
$: x = (point: Color) => xScale(point.toChannels()[1]);
Expand All @@ -270,6 +270,8 @@
const avgNums = (nums: number[]) =>
nums.reduce((acc, x) => acc + x, 0) / nums.length;
const bgResolution = 25;
</script>

<!-- svelte-ignore a11y-no-static-element-interactions -->
Expand All @@ -292,39 +294,30 @@
on:touchend={stopDrag}
>
<g transform={`translate(${margin.left}, ${margin.top})`}>
{#if dragging && focusedColors.length}
{#each [...new Array(50)] as _, i}
{#each [...new Array(50)] as _, j}
<rect
x={xScale(xNonDimScale(i / 50))}
y={yScale(yNonDimScale(j / 50))}
width={plotWidth / 50}
height={plotHeight / 50}
opacity="0.9"
fill={colorFromChannels(
[
avgNums(
focusedColors.map((x) => colors[x].toChannels()[0])
),
xNonDimScale(i / 50),
yNonDimScale(j / 50),
],
colorSpace
).toHex()}
/>
{/each}
{#each [...new Array(bgResolution)] as _, i}
{#each [...new Array(bgResolution)] as _, j}
<rect
x={xScale(xNonDimScale(i / bgResolution))}
y={yScale(yNonDimScale(j / bgResolution))}
width={plotWidth / bgResolution}
height={plotHeight / bgResolution}
opacity="1"
fill={dragging && focusedColors.length
? colorFromChannels(
[
avgNums(
focusedColors.map((x) => colors[x].toChannels()[0])
),
xNonDimScale(i / bgResolution),
yNonDimScale(j / bgResolution),
],
colorSpace
).toHex()
: bg.toHex()}
/>
{/each}
{:else}
<rect
x={0}
y={0}
width={xScale.range()[1]}
height={yScale.range()[1]}
fill={bg.toHex()}
stroke={axisColor}
stroke-width="1"
/>
{/if}
{/each}

<line
x1={points.centerTop.x}
y1={points.centerTop.y}
Expand All @@ -346,7 +339,7 @@
text-anchor={point.anchor}
x={point.x + point.labelAdjust.x}
y={point.y + point.labelAdjust.y}
fill={bg.toChroma().luminance() > 0.5 ? "black" : "white"}
fill={bg.luminance() > 0.5 ? "black" : "white"}
>
{point.label}
</text>
Expand Down Expand Up @@ -449,7 +442,7 @@
<text
x={xScale(bg.toChannels()[1])}
y={yScale(bg.toChannels()[2])}
fill={bg.toChroma().luminance() > 0.5 ? "black" : "white"}
fill={bg.luminance() > 0.5 ? "black" : "white"}
text-anchor="middle"
alignment-baseline="middle"
class="pointer-events-none"
Expand Down Expand Up @@ -526,7 +519,7 @@
text-anchor={"middle"}
x={40}
y={point.y}
fill={bg.toChroma().luminance() > 0.5 ? "black" : "white"}
fill={bg.luminance() > 0.5 ? "black" : "white"}
>
{point.label}
</text>
Expand Down
2 changes: 1 addition & 1 deletion src/content-modules/Background.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
let:toggle
slot="target"
class={"cursor-pointer mr-2 mb-2 w-full h-8 rounded-full border-2 border-gray-200 text-center"}
class:text-white={bg.toChroma().luminance() < 0.5}
class:text-white={bg.luminance() < 0.5}
style={`background: ${bg.toHex()}`}
on:click={() => {
toggle();
Expand Down
2 changes: 1 addition & 1 deletion src/content-modules/Eval.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
focusStore.setColors([idx]);
}}
class="w-48 flex flex-col justify-center items-center text-sm mt-2 transition-all relative"
class:text-white={color.toChroma().luminance() < 0.5}
class:text-white={color.luminance() < 0.5}
class:ml-5={$focusStore.focusedColors.includes(idx)}
class:mr-5={!$focusStore.focusedColors.includes(idx)}
style="min-height: 40px"
Expand Down
5 changes: 1 addition & 4 deletions src/content-modules/Swatches.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@
style={`background-color: ${bg.toHex()}; max-width: 600px`}
>
<div class="flex mb-2 justify-between items-center">
<span
class="text-sm flex flex-col"
class:text-white={bg.toChroma().luminance() < 0.5}
>
<span class="text-sm flex flex-col" class:text-white={bg.luminance() < 0.5}>
<span>Click to modify colors</span>
<span>Hold shift to select multiple</span>
</span>
Expand Down
6 changes: 2 additions & 4 deletions src/content-modules/TextBlock.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
...colors.map(
(color) =>
`background-color: ${color.toHex()};
color: ${
color.toChroma().luminance() > 0.5 ? "white" : "black"
};`
color: ${color.luminance() > 0.5 ? "white" : "black"};`
),
...new Array(20).map(() => ""),
];
Expand All @@ -28,7 +26,7 @@
<p
class="max-w-sm flex flex-wrap text-sm"
style="background-color: {bg.toHex()};"
class:text-white={bg.toChroma().luminance() < 0.5}
class:text-white={bg.luminance() < 0.5}
>
{#each wordBreakDown as { word, style }}
<span {style} class="mr-1 transition-all">{` ${word} `}</span>
Expand Down
145 changes: 65 additions & 80 deletions src/lib/Color.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import type { Color as ChromaColor } from "chroma-js";
import chroma from "chroma-js";
import ColorIO from "colorjs.io";

const hexCache = new Map<string, string>();
export class Color {
name: string;
channels: Record<string, number>;
chromaBind: typeof chroma.lab;
spaceName: keyof typeof colorDirectory;
constructor() {
this.name = "";
this.channels = {};
this.chromaBind = chroma.rgb;
this.spaceName = "rgb";
}
name: string = "";
channels: Record<string, number> = {};
chromaBind: typeof chroma.lab = chroma.rgb;
spaceName: keyof typeof colorDirectory = "rgb";

toHex(): string {
return this.chromaBind(...this.toChannels()).hex();
const str = this.toString();
if (hexCache.has(str)) {
return hexCache.get(str) as string;
}
const newHex = this.toColorIO().to("srgb").toString({ format: "hex" });
// const oldHex = this.chromaBind(...this.toChannels()).hex();
// console.log(newHex, oldHex);
// return this.chromaBind(...this.toChannels()).hex();
hexCache.set(str, newHex);
return newHex;
}
toString(): string {
const channelsString = Object.values(this.channels)
Expand Down Expand Up @@ -70,115 +75,89 @@ export class Color {
});
return newColor;
}
luminance(): number {
return chroma(this.toHex()).luminance();
}
deltaE(color: Color): number {
return chroma.deltaE(this.toChroma(), color.toChroma());
}
symmetricDeltaE(color: Color): number {
return 0.5 * (this.deltaE(color) + color.deltaE(this));
}
}

export class CIELAB extends Color {
name: "CIELAB";
channels: { L: number; a: number; b: number };
constructor() {
super();
this.name = "CIELAB";
this.channels = { L: 0, a: 0, b: 0 };
this.chromaBind = chroma.lab;
this.spaceName = "lab";
}
name = "CIELAB";
channels = { L: 0, a: 0, b: 0 };
chromaBind = chroma.lab;
spaceName = "lab" as const;

toString(): string {
const [L, a, b] = Object.values(this.channels).map((x) => x || 0);
// .map((x) => x.toPrecision(1));
return `lab(${L}% ${a} ${b})`;
}
}
export class HSV extends Color {
name: "HSV";
channels: { h: number; s: number; v: number };
constructor() {
super();
this.name = "HSV";
this.channels = { h: 0, s: 0, v: 0 };
this.chromaBind = chroma.hsv;
this.spaceName = "hsv";
}
name = "HSV";
channels = { h: 0, s: 0, v: 0 };
chromaBind = chroma.hsv;
spaceName = "hsv" as const;
toString(): string {
const [h, s, v] = Object.values(this.channels);
return `color(hsv ${h} ${s} ${v})`;
}
}

export class RGB extends Color {
name: "RGB";
channels: { r: number; g: number; b: number };
constructor() {
super();
this.name = "RGB";
this.channels = { r: 0, g: 0, b: 0 };
this.chromaBind = chroma.rgb;
this.spaceName = "rgb";
}
name = "RGB";
channels = { r: 0, g: 0, b: 0 };
chromaBind = chroma.rgb;
spaceName = "rgb" as const;
}

export class HSL extends Color {
name: "HSL";
channels: { h: number; s: number; l: number };
constructor() {
super();
this.name = "HSL";
this.channels = { h: 0, s: 0, l: 0 };
this.chromaBind = chroma.hsl;
this.spaceName = "hsl";
}
name = "HSL";
channels = { h: 0, s: 0, l: 0 };
chromaBind = chroma.hsl;
spaceName = "hsl" as const;

toString(): string {
const [h, s, l] = Object.values(this.channels).map((x) => x || 0);
return `hsl(${h} ${s}% ${l}%)`;
}
}
export class LCH extends Color {
name: "LCH";
channels: { l: number; c: number; h: number };
constructor() {
super();
this.name = "LCH";
this.channels = { l: 0, c: 0, h: 0 };
this.chromaBind = chroma.lch;
this.spaceName = "lch";
}
name = "LCH";
channels = { l: 0, c: 0, h: 0 };
chromaBind = chroma.lch;
spaceName = "lch" as const;
}

export class OKLAB extends Color {
name: "OKLAB";
channels: { l: number; a: number; b: number };
constructor() {
super();
this.name = "OKLAB";
this.channels = { l: 0, a: 0, b: 0 };
this.chromaBind = chroma.oklab;
this.spaceName = "oklab";
}
name = "OKLAB";
channels = { l: 0, a: 0, b: 0 };
chromaBind = chroma.oklab;
spaceName = "oklab" as const;
}

export class OKLCH extends Color {
name: "OKLCH";
channels: { l: number; c: number; h: number };
constructor() {
super();
this.name = "OKLCH";
this.channels = { l: 0, c: 0, h: 0 };
this.chromaBind = chroma.oklch;
this.spaceName = "oklch";
}
name = "OKLCH";
channels = { l: 0, c: 0, h: 0 };
chromaBind = chroma.oklch;
spaceName = "oklch" as const;
}

export class JZAZBZ extends Color {
name: "JZAZBZ";
channels: { jz: number; az: number; bz: number };
name = "JZAZBZ";
channels = { jz: 0, az: 0, bz: 0 };
spaceName = "jzazbz" as const;
constructor() {
super();
this.name = "JZAZBZ";
this.channels = { jz: 0, az: 0, bz: 0 };
this.chromaBind = (jz, az, bz) => {
const [l, a, b] = new ColorIO(this.toString()).to("lab").coords;
return chroma.lab(l, a, b);
};
this.spaceName = "jzazbz";
}
toString(): string {
const [jz, az, bz] = Object.values(this.channels);
Expand All @@ -193,12 +172,18 @@ export function colorFromString(
return new colorDirectory[colorSpace]().fromString(colorString);
}

const colorHexCache = new Map<string, Color>();
export function colorFromHex(
hex: string,
colorSpace: keyof typeof colorDirectory
): Color {
if (colorHexCache.has(hex)) {
return { ...colorHexCache.get(hex) } as Color;
}
const color = new ColorIO(hex).to(colorSpace);
return new colorDirectory[colorSpace]().fromChannels(color.coords);
const outColor = new colorDirectory[colorSpace]().fromChannels(color.coords);
colorHexCache.set(hex, outColor);
return outColor;
// const color = chroma(hex);
// return new colorDirectory[colorSpace]().fromChroma(color);
}
Expand Down
3 changes: 1 addition & 2 deletions src/lib/charts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export function buildTheme(pal: Palette): any {

const fontStandard = "Montserrat, sans-serif UI";
const fontTitle = "wf_standard-font, helvetica, arial, sans-serif";
const basicColor =
pal.background.toChroma().luminance() > 0.5 ? "#000000" : "#ffffff";
const basicColor = pal.background.luminance() > 0.5 ? "#000000" : "#ffffff";
// const secondLevelElementColor = "#605E5C";
// const backgroundColor = pal.background.toHex();
const backgroundColor = "SaLmOn";
Expand Down
2 changes: 2 additions & 0 deletions src/lib/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import BackgroundDifferentiability from "./lints/background-differentiability";
import UglyColors from "./lints/ugly-colors";
import SequentialOrder from "./lints/sequential-order";
import AvoidExtremes from "./lints/avoid-extremes";
import DivergingOrder from "./lints/diverging-order";

export function runLintChecks(palette: Palette): ColorLint<any, any>[] {
return [
Expand All @@ -22,5 +23,6 @@ export function runLintChecks(palette: Palette): ColorLint<any, any>[] {
new UglyColors(palette),
new SequentialOrder(palette),
new AvoidExtremes(palette),
new DivergingOrder(palette),
];
}
Loading

0 comments on commit b402c66

Please sign in to comment.