完成Mixer功能的设计。
This commit is contained in:
parent
251e86b0b4
commit
a94626c192
@ -5,6 +5,7 @@ import { Harmonies } from './pages/Harmonies';
|
||||
import { Home } from './pages/Home';
|
||||
import { LightenDarken } from './pages/LightenDarken';
|
||||
import { MainLayout } from './pages/MainLayout';
|
||||
import { Mixer } from './pages/Mixer';
|
||||
import { NewScheme } from './pages/NewScheme';
|
||||
import { SchemeDetail } from './pages/SchemeDetail';
|
||||
import { SchemeNotFound } from './pages/SchemeNotFound';
|
||||
@ -33,6 +34,7 @@ const routes = createBrowserRouter([
|
||||
{ path: 'tones', element: <Tones /> },
|
||||
{ path: 'tints-shades', element: <TintsShades /> },
|
||||
{ path: 'lighten-darken', element: <LightenDarken /> },
|
||||
{ path: 'mixer', element: <Mixer /> },
|
||||
],
|
||||
},
|
||||
]);
|
||||
|
34
src/pages/Mixer.module.css
Normal file
34
src/pages/Mixer.module.css
Normal file
@ -0,0 +1,34 @@
|
||||
@layer pages {
|
||||
.mixer_workspace {
|
||||
flex-direction: column;
|
||||
}
|
||||
.mixer_content {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-around;
|
||||
align-items: flex-start;
|
||||
gap: var(--spacing-m);
|
||||
.mixer_column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-s);
|
||||
font-size: var(--font-size-s);
|
||||
.color_value_mode {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--spacing-s);
|
||||
font-size: var(--font-size-s);
|
||||
}
|
||||
.colors_booth {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: stretch;
|
||||
gap: var(--spacing-xs);
|
||||
min-height: 12em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
79
src/pages/Mixer.tsx
Normal file
79
src/pages/Mixer.tsx
Normal file
@ -0,0 +1,79 @@
|
||||
import cx from 'clsx';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useColorFunction } from '../ColorFunctionContext';
|
||||
import { ColorPicker } from '../components/ColorPicker';
|
||||
import { FlexColorStand } from '../components/FlexColorStand';
|
||||
import { HSegmentedControl } from '../components/HSegmentedControl';
|
||||
import { LabeledPicker } from '../components/LabeledPicker';
|
||||
import { ScrollArea } from '../components/ScrollArea';
|
||||
import styles from './Mixer.module.css';
|
||||
|
||||
export function Mixer() {
|
||||
const { colorFn } = useColorFunction();
|
||||
const [basicColor, setBasicColor] = useState('000000');
|
||||
const [mixColor, setMixColor] = useState('000000');
|
||||
const [mixRatio, setMixRatio] = useState(0);
|
||||
const [mode, setMode] = useState<'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch'>('hex');
|
||||
const mixedColor = useMemo(() => {
|
||||
try {
|
||||
if (!colorFn) {
|
||||
return '000000';
|
||||
}
|
||||
const mixed = colorFn.mix(basicColor, mixColor, mixRatio / 100);
|
||||
return mixed;
|
||||
} catch (e) {
|
||||
console.error('[Mix Color]', e);
|
||||
}
|
||||
return '000000';
|
||||
}, [basicColor, mixColor, mixRatio]);
|
||||
|
||||
return (
|
||||
<div className={cx('workspace', styles.mixer_workspace)}>
|
||||
<header>
|
||||
<h3>Color Mixer</h3>
|
||||
<p>Make a new color by mixing two colors.</p>
|
||||
</header>
|
||||
<ScrollArea enableY>
|
||||
<div className={styles.mixer_content}>
|
||||
<div className={styles.mixer_column}>
|
||||
<h5>Basic Color</h5>
|
||||
<ColorPicker color={basicColor} onSelect={setBasicColor} />
|
||||
</div>
|
||||
<div className={styles.mixer_column}>
|
||||
<h5>Mix Color</h5>
|
||||
<ColorPicker color={mixColor} onSelect={setMixColor} />
|
||||
<LabeledPicker
|
||||
title="Mix Ratio"
|
||||
value={mixRatio}
|
||||
onChange={setMixRatio}
|
||||
min={0}
|
||||
max={100}
|
||||
step={1}
|
||||
unit="%"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.mixer_column}>
|
||||
<h5>Mix Result</h5>
|
||||
<div className={styles.colors_booth}>
|
||||
<FlexColorStand color={mixedColor} valueMode={mode} />
|
||||
</div>
|
||||
<div className={styles.color_value_mode}>
|
||||
<label>Copy color value in</label>
|
||||
<HSegmentedControl
|
||||
options={[
|
||||
{ label: 'HEX', value: 'hex' },
|
||||
{ label: 'RGB', value: 'rgb' },
|
||||
{ label: 'HSL', value: 'hsl' },
|
||||
{ label: 'LAB', value: 'lab' },
|
||||
{ label: 'OKLCH', value: 'oklch' },
|
||||
]}
|
||||
value={mode}
|
||||
onChange={setMode}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</div>
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user