|
1 | | -import React from 'react'; |
| 1 | +import React, { useCallback, useMemo } from 'react'; |
2 | 2 | import Alpha, { AlphaProps } from '@uiw/react-color-alpha'; |
3 | 3 |
|
| 4 | +const NORMAL_COLORS = |
| 5 | + 'rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%'; |
| 6 | +const REVERSED_COLORS = |
| 7 | + 'rgb(255, 0, 0) 0%, rgb(255, 0, 255) 17%, rgb(0, 0, 255) 33%, rgb(0, 255, 255) 50%, rgb(0, 255, 0) 67%, rgb(255, 255, 0) 83%, rgb(255, 0, 0) 100%'; |
| 8 | + |
4 | 9 | export interface HueProps extends Omit<AlphaProps, 'hsva' | 'onChange'> { |
5 | 10 | onChange?: (newHue: { h: number }) => void; |
6 | 11 | hue?: number; |
7 | 12 | } |
8 | 13 |
|
9 | 14 | const Hue = React.forwardRef<HTMLDivElement, HueProps>((props, ref) => { |
10 | | - const { prefixCls = 'w-color-hue', className, hue = 0, onChange, direction = 'horizontal', ...other } = props; |
| 15 | + const { prefixCls = 'w-color-hue', className, hue = 0, onChange, direction = 'horizontal', reverse = false, ...other } = props; |
| 16 | + |
| 17 | + const getGradientBackground = useCallback(() => { |
| 18 | + if (direction === 'horizontal') { |
| 19 | + const colors = reverse ? REVERSED_COLORS : NORMAL_COLORS; |
| 20 | + const gradientDirection = 'right'; |
| 21 | + return `linear-gradient(to ${gradientDirection}, ${colors})`; |
| 22 | + } else { |
| 23 | + // 垂直模式下,由于交互逻辑使用了 1-value,所以渐变颜色也要反转 |
| 24 | + const colors = reverse ? NORMAL_COLORS : REVERSED_COLORS; |
| 25 | + const gradientDirection = 'bottom'; |
| 26 | + return `linear-gradient(to ${gradientDirection}, ${colors})`; |
| 27 | + } |
| 28 | + }, [direction, reverse]); |
| 29 | + |
| 30 | + const getHueFromInteraction = useCallback( |
| 31 | + (interaction: any) => { |
| 32 | + const value = direction === 'horizontal' ? interaction.left : interaction.top; |
| 33 | + let normalizedValue; |
| 34 | + if (direction === 'horizontal') { |
| 35 | + normalizedValue = reverse ? 1 - value : value; |
| 36 | + } else { |
| 37 | + // 垂直模式下,正常情况下顶部应该是0,底部是360,所以需要反转 |
| 38 | + normalizedValue = reverse ? value : 1 - value; |
| 39 | + } |
| 40 | + return 360 * normalizedValue; |
| 41 | + }, |
| 42 | + [direction, reverse], |
| 43 | + ); |
| 44 | + |
| 45 | + const gradientBackground = useMemo(() => getGradientBackground(), [getGradientBackground]); |
| 46 | + |
11 | 47 | return ( |
12 | 48 | <Alpha |
13 | 49 | ref={ref} |
14 | 50 | className={`${prefixCls} ${className || ''}`} |
15 | 51 | {...other} |
16 | 52 | direction={direction} |
17 | | - background={`linear-gradient(to ${ |
18 | | - direction === 'horizontal' ? 'right' : 'bottom' |
19 | | - }, rgb(255, 0, 0) 0%, rgb(255, 255, 0) 17%, rgb(0, 255, 0) 33%, rgb(0, 255, 255) 50%, rgb(0, 0, 255) 67%, rgb(255, 0, 255) 83%, rgb(255, 0, 0) 100%)`} |
| 53 | + reverse={reverse} |
| 54 | + background={gradientBackground} |
20 | 55 | hsva={{ h: hue, s: 100, v: 100, a: hue / 360 }} |
21 | 56 | onChange={(_, interaction) => { |
22 | | - onChange && onChange({ h: direction === 'horizontal' ? 360 * interaction.left : 360 * interaction.top }); |
| 57 | + onChange && onChange({ h: getHueFromInteraction(interaction) }); |
23 | 58 | }} |
24 | 59 | /> |
25 | 60 | ); |
|
0 commit comments