完成Mixer功能的设计。
This commit is contained in:
		| @@ -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> | ||||
|   ); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user