From 1edc74daaf77c2538238f2176dcc87997cc84371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=B6=9B?= Date: Mon, 13 Jan 2025 17:08:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=A2=9C=E8=89=B2=E5=AF=B9?= =?UTF-8?q?=E6=AF=94=E5=8A=9F=E8=83=BD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.tsx | 2 + .../color-compare/CompareLayout.module.css | 25 ++++++ .../color-compare/HCTCompare.tsx | 74 ++++++++++++++++++ .../color-compare/HSLCompare.tsx | 77 ++++++++++++++++++ .../color-compare/OKLCHCompare.tsx | 74 ++++++++++++++++++ .../color-compare/RGBCompare.tsx | 78 +++++++++++++++++++ .../color-compare/share-props.ts | 4 + src/pages/Compare.module.css | 18 +++++ src/pages/Compare.tsx | 44 +++++++++++ 9 files changed, 396 insertions(+) create mode 100644 src/page-components/color-compare/CompareLayout.module.css create mode 100644 src/page-components/color-compare/HCTCompare.tsx create mode 100644 src/page-components/color-compare/HSLCompare.tsx create mode 100644 src/page-components/color-compare/OKLCHCompare.tsx create mode 100644 src/page-components/color-compare/RGBCompare.tsx create mode 100644 src/page-components/color-compare/share-props.ts create mode 100644 src/pages/Compare.module.css create mode 100644 src/pages/Compare.tsx diff --git a/src/App.tsx b/src/App.tsx index 98c5a64..7f91fc7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -3,6 +3,7 @@ import { ColorFunctionProvider } from './ColorFunctionContext'; import { Notifications } from './components/Notifications'; import { ColorCards } from './pages/Cards'; import { CardsDetail } from './pages/CardsDetail'; +import { ColorCompare } from './pages/Compare'; import { Harmonies } from './pages/Harmonies'; import { Home } from './pages/Home'; import { LightenDarken } from './pages/LightenDarken'; @@ -39,6 +40,7 @@ const routes = createBrowserRouter([ { path: 'lighten-darken', element: }, { path: 'mixer', element: }, { path: 'wacg', element: }, + { path: 'compare', element: }, { path: 'cards', element: , diff --git a/src/page-components/color-compare/CompareLayout.module.css b/src/page-components/color-compare/CompareLayout.module.css new file mode 100644 index 0000000..2bc395e --- /dev/null +++ b/src/page-components/color-compare/CompareLayout.module.css @@ -0,0 +1,25 @@ +@layer pages { + .elements { + display: flex; + flex-direction: row; + align-items: stretch; + gap: var(--spacing-m); + .element { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--spacing-xs); + .element_name { + font-size: var(--font-size-xxl); + font-weight: bold; + } + .element_values { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + font-size: var(--font-size-xs); + line-height: var(--font-size-xs); + } + } + } +} diff --git a/src/page-components/color-compare/HCTCompare.tsx b/src/page-components/color-compare/HCTCompare.tsx new file mode 100644 index 0000000..59e0dc0 --- /dev/null +++ b/src/page-components/color-compare/HCTCompare.tsx @@ -0,0 +1,74 @@ +import { useMemo } from 'react'; +import { HctDiffference } from '../../color_functions/color_module'; +import { useColorFunction } from '../../ColorFunctionContext'; +import styles from './CompareLayout.module.css'; +import { CompareMethodProps } from './share-props'; + +const defaultCompareResult: HctDiffference = { + hue: { + delta: 0, + percent: 0, + }, + chroma: { + delta: 0, + percent: 0, + }, + lightness: { + delta: 0, + percent: 0, + }, +}; + +export function HCTCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) { + const { colorFn } = useColorFunction(); + const differ = useMemo(() => { + if (!colorFn) { + return defaultCompareResult; + } + try { + const diff = colorFn.differ_in_hct(basic, compare); + return diff; + } catch (e) { + console.error('[Compare in HCT]', e); + } + return defaultCompareResult; + }, [basic, compare]); + + return ( +
+
Compare in HCT Space
+
+
+
H
+
+ {differ.hue.delta.toFixed(2)} + + {isNaN(differ.hue.percent) ? '0.00' : (differ.hue.percent * 100).toFixed(2)}% + +
+
+
+
C
+
+ {differ.chroma.delta.toFixed(2)} + + {isNaN(differ.chroma.percent) ? '0.00' : (differ.chroma.percent * 100).toFixed(2)}% + +
+
+
+
T
+
+ {differ.lightness.delta.toFixed(2)} + + {isNaN(differ.lightness.percent) + ? '0.00' + : (differ.lightness.percent * 100).toFixed(2)} + % + +
+
+
+
+ ); +} diff --git a/src/page-components/color-compare/HSLCompare.tsx b/src/page-components/color-compare/HSLCompare.tsx new file mode 100644 index 0000000..4e4d114 --- /dev/null +++ b/src/page-components/color-compare/HSLCompare.tsx @@ -0,0 +1,77 @@ +import { useMemo } from 'react'; +import { HSLDifference } from '../../color_functions/color_module'; +import { useColorFunction } from '../../ColorFunctionContext'; +import styles from './CompareLayout.module.css'; +import { CompareMethodProps } from './share-props'; + +const defaultCompareResult: HSLDifference = { + hue: { + delta: 0, + percent: 0, + }, + saturation: { + delta: 0, + percent: 0, + }, + lightness: { + delta: 0, + percent: 0, + }, +}; + +export function HSLCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) { + const { colorFn } = useColorFunction(); + const differ = useMemo(() => { + if (!colorFn) { + return defaultCompareResult; + } + try { + const diff = colorFn.differ_in_hsl(basic, compare); + return diff; + } catch (e) { + console.error('[Compare in HSL]', e); + } + return defaultCompareResult; + }, [basic, compare]); + + return ( +
+
Compare in HSL Space
+
+
+
H
+
+ {differ.hue.delta.toFixed(2)} + + {isNaN(differ.hue.percent) ? '0.00' : (differ.hue.percent * 100).toFixed(2)}% + +
+
+
+
S
+
+ {(differ.saturation.delta * 100).toFixed(2)}% + + {isNaN(differ.saturation.percent) + ? '0.00' + : (differ.saturation.percent * 100).toFixed(2)} + % + +
+
+
+
L
+
+ {(differ.lightness.delta * 100).toFixed(2)}% + + {isNaN(differ.lightness.percent) + ? '0.00' + : (differ.lightness.percent * 100).toFixed(2)} + % + +
+
+
+
+ ); +} diff --git a/src/page-components/color-compare/OKLCHCompare.tsx b/src/page-components/color-compare/OKLCHCompare.tsx new file mode 100644 index 0000000..b7263a7 --- /dev/null +++ b/src/page-components/color-compare/OKLCHCompare.tsx @@ -0,0 +1,74 @@ +import { useMemo } from 'react'; +import { OklchDifference } from '../../color_functions/color_module'; +import { useColorFunction } from '../../ColorFunctionContext'; +import styles from './CompareLayout.module.css'; +import { CompareMethodProps } from './share-props'; + +const defaultCompareResult: OklchDifference = { + hue: { + delta: 0, + percent: 0, + }, + chroma: { + delta: 0, + percent: 0, + }, + lightness: { + delta: 0, + percent: 0, + }, +}; + +export function OklchCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) { + const { colorFn } = useColorFunction(); + const differ = useMemo(() => { + if (!colorFn) { + return defaultCompareResult; + } + try { + const diff = colorFn.differ_in_oklch(basic, compare); + return diff; + } catch (e) { + console.error('[Compare in Oklch]', e); + } + return defaultCompareResult; + }, [basic, compare]); + + return ( +
+
Compare in Oklch Space
+
+
+
L
+
+ {(differ.lightness.delta * 100).toFixed(2)}% + + {isNaN(differ.lightness.percent) + ? '0.0000' + : (differ.lightness.percent * 100).toFixed(2)} + % + +
+
+
+
C
+
+ {differ.chroma.delta.toFixed(4)} + + {isNaN(differ.chroma.percent) ? '0.0000' : (differ.chroma.percent * 100).toFixed(2)}% + +
+
+
+
H
+
+ {differ.hue.delta.toFixed(2)} + + {isNaN(differ.hue.percent) ? '0.00' : (differ.hue.percent * 100).toFixed(2)}% + +
+
+
+
+ ); +} diff --git a/src/page-components/color-compare/RGBCompare.tsx b/src/page-components/color-compare/RGBCompare.tsx new file mode 100644 index 0000000..fb7262c --- /dev/null +++ b/src/page-components/color-compare/RGBCompare.tsx @@ -0,0 +1,78 @@ +import { useMemo } from 'react'; +import { RGBDifference } from '../../color_functions/color_module'; +import { useColorFunction } from '../../ColorFunctionContext'; +import styles from './CompareLayout.module.css'; +import { CompareMethodProps } from './share-props'; + +const defaultCompareResult: RGBDifference = { + r: { + delta: 0, + percent: 0, + }, + g: { + delta: 0, + percent: 0, + }, + b: { + delta: 0, + percent: 0, + }, +}; + +export function RGBCompare({ basic = '000000', compare = '000000' }: CompareMethodProps) { + const { colorFn } = useColorFunction(); + const differ = useMemo(() => { + if (!colorFn) { + return defaultCompareResult; + } + try { + const diff = colorFn?.differ_in_rgb(basic, compare); + return { + r: { + delta: Math.round(diff.r.delta * 255), + percent: diff.r.percent, + }, + g: { + delta: Math.round(diff.g.delta * 255), + percent: diff.g.percent, + }, + b: { + delta: Math.round(diff.b.delta * 255), + percent: diff.b.percent, + }, + } as RGBDifference; + } catch (e) { + console.error('[Compare in RGB]', e); + } + return defaultCompareResult; + }, [basic, compare]); + + return ( +
+
Compare in RGB Space
+
+
+
R
+
+ {differ.r.delta} + {isNaN(differ.r.percent) ? '0.00' : (differ.r.percent * 100).toFixed(2)}% +
+
+
+
G
+
+ {differ.g.delta} + {isNaN(differ.g.percent) ? '0.00' : (differ.g.percent * 100).toFixed(2)}% +
+
+
+
B
+
+ {differ.b.delta} + {isNaN(differ.b.percent) ? '0.00' : (differ.b.percent * 100).toFixed(2)}% +
+
+
+
+ ); +} diff --git a/src/page-components/color-compare/share-props.ts b/src/page-components/color-compare/share-props.ts new file mode 100644 index 0000000..31da566 --- /dev/null +++ b/src/page-components/color-compare/share-props.ts @@ -0,0 +1,4 @@ +export type CompareMethodProps = { + basic?: string; + compare?: string; +}; diff --git a/src/pages/Compare.module.css b/src/pages/Compare.module.css new file mode 100644 index 0000000..f88020d --- /dev/null +++ b/src/pages/Compare.module.css @@ -0,0 +1,18 @@ +@layer pages { + .compare_workspace { + flex-direction: column; + } + .compare_content { + width: 100%; + display: flex; + flex-direction: row; + align-items: flex-start; + gap: var(--spacing-l); + .compare_column { + display: flex; + flex-direction: column; + gap: var(--spacing-s); + font-size: var(--font-size-s); + } + } +} diff --git a/src/pages/Compare.tsx b/src/pages/Compare.tsx new file mode 100644 index 0000000..e03a999 --- /dev/null +++ b/src/pages/Compare.tsx @@ -0,0 +1,44 @@ +import cx from 'clsx'; +import { useState } from 'react'; +import { ColorPicker } from '../components/ColorPicker'; +import { ScrollArea } from '../components/ScrollArea'; +import { HCTCompare } from '../page-components/color-compare/HCTCompare'; +import { HSLCompare } from '../page-components/color-compare/HSLCompare'; +import { OklchCompare } from '../page-components/color-compare/OKLCHCompare'; +import { RGBCompare } from '../page-components/color-compare/RGBCompare'; +import styles from './Compare.module.css'; + +export function ColorCompare() { + const [basicColor, setBasicColor] = useState('000000'); + const [compareColor, setCompareColor] = useState('000000'); + + return ( +
+
+

Color Compare

+

+ Compare the properties of two colors and find the associated patterns of color change. +

+
+ +
+
+
Basic Color
+ +
+
+
Compare Color
+ +
+
+
Compare Result
+ + + + +
+
+
+
+ ); +}