Skip to content

Commit

Permalink
✨ feat: 支持各方向灵活切换
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Apr 6, 2022
1 parent 40e3594 commit 86923c8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 30 deletions.
12 changes: 6 additions & 6 deletions packages/color-picker/src/components/Alpha/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type { FC } from 'react';
import React, { memo, useEffect, useMemo, useRef } from 'react';

import isEqual from 'lodash/isEqual';
import { concatMap, map, takeUntil } from 'rxjs/operators';

import Checkboard from '../common/Checkboard';
import { colorSelector, useStore } from '../../store';
import { useStore } from '../../store';

import styles from './style.less';
import { fromEvent, Subject } from 'rxjs';

const Alpha: FC = memo(() => {
const { rgb } = useStore(colorSelector, isEqual);
const rgb = useStore((s) => s.colorModel.rgb());
const alpha = useStore((s) => s.colorModel.alpha());
const updateAlpha = useStore((s) => s.updateAlpha);

const ctnRef = useRef(null);
Expand Down Expand Up @@ -48,8 +48,8 @@ const Alpha: FC = memo(() => {
<div
className={styles.background}
style={{
background: `linear-gradient(to right, rgba(${rgb.r},${rgb.g},${rgb.b}, 0) 0%,
rgba(${rgb.r},${rgb.g},${rgb.b}, 1) 100%)`,
background: `linear-gradient(to right, rgba(${rgb.join(',')}, 0) 0%,
rgba(${rgb.join(',')}, 1) 100%)`,
}}
/>
<div
Expand All @@ -62,7 +62,7 @@ const Alpha: FC = memo(() => {
<div
style={{
position: 'absolute',
left: `${rgb.a * 100}%`,
left: `${alpha * 100}%`,
}}
>
<div className={styles.slider} />
Expand Down
10 changes: 5 additions & 5 deletions packages/color-picker/src/components/Saturation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import reactCSS from 'reactcss';

import { fromEvent, Subject } from 'rxjs';
import { concatMap, map, takeUntil, throttleTime } from 'rxjs/operators';
import { colorSelector, useStore } from '@arvinxu/color-picker/store';
import { useStore } from '../../store';

export const Saturation: FC = () => {
const hue = useStore((s) => s.hue);
const saturation = useStore((s) => s.saturation);
const brightness = useStore((s) => s.brightness);

const updateBySV = useStore((s) => s.updateBySV);

const { hsv } = useStore(colorSelector);

const ctnRef = useRef(null);

const getContainerRenderWindow = () => {
Expand Down Expand Up @@ -82,8 +82,8 @@ export const Saturation: FC = () => {
},
pointer: {
position: 'absolute',
top: `${-(hsv.v * 100) + 100}%`,
left: `${hsv.s * 100}%`,
top: `${100 - brightness}%`,
left: `${saturation}%`,
cursor: 'default',
},
circle: {
Expand Down
70 changes: 51 additions & 19 deletions packages/color-picker/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ interface ColorPickerState {
onChange?: ({ hex, color }: { hex: string; color: Color }) => void;
colorModel: Color;
hue: number;
saturation: number;
brightness: number;
}
interface ColorPickerAction {
internalUpdateColor: (color: Color) => void;
Expand All @@ -26,6 +28,7 @@ interface ColorPickerAction {
updateByHex: (hex: string) => void;
updateBySV: (saturation: number, value: number) => void;
updateByRgb: (rgb: RGBColor) => void;
getColorModelByHSV: (h?: number, s?: number, v?: number) => Color;
}

export type ColorPickerStore = ColorPickerState & ColorPickerAction;
Expand Down Expand Up @@ -65,6 +68,8 @@ const initialState: ColorPickerState = {
// 这会破坏基础的预期
// 取色器中
hue: 250,
brightness: 30,
saturation: 68,
};

const createStore = () => {
Expand All @@ -73,11 +78,26 @@ const createStore = () => {
(set, get) => ({
...initialState,

getColorModelByHSV: (h, s, v) => {
const { hue, saturation, brightness, colorModel } = get();
return chroma(
h ?? hue,
s ?? saturation / 100,
v ?? brightness / 100,
colorModel.alpha(),
'hsv',
);
},
updateColorMode: (mode) => {
set({ colorMode: mode });
},

internalUpdateColor: (color) => {
// 如果 color 的 h s v 都是 NaN,那么就要用保存值来替换
if (color.hsv().every((x) => isNaN(x))) {
color = get().getColorModelByHSV();
}

set({ colorModel: color });

if (get().onChange) {
Expand All @@ -99,25 +119,43 @@ const createStore = () => {

updateHue: (h) => {
const { colorModel, internalUpdateColor } = get();
set({ hue: h });
internalUpdateColor(colorModel.set('hsl.h', h));
},

updateByColorSpace: (key, value) => {
const { colorModel, internalUpdateColor, colorMode } = get();
const { colorModel, updateHue, internalUpdateColor, colorMode } = get();
let v;

// 将值限定在相应的最大区间内
v = value > maxValueMap[key] ? maxValueMap[key] : value;
// 且确保 v 最小值为 0
if (value < 0) v = 0;

// 如果是 hue 的更新
if (key === 'h') {
updateHue(value);
return;
}

// 如果是 s v l 三个维度值,将其转换为百分比

if (['s', 'v', 'l'].includes(key)) {
v /= 100;
}

internalUpdateColor(colorModel.set(`${colorMode}.${key}`, v));

if (colorMode === 'hsv') {
switch (key) {
case 's':
set({ saturation: v * 100 });
break;
case 'v':
set({ brightness: v * 100 });
break;
}
}
},

updateByHex: (hex) => {
Expand All @@ -127,7 +165,7 @@ const createStore = () => {
},

updateBySV: (saturation, value) => {
const { internalUpdateColor, colorModel, hue } = get();
const { internalUpdateColor, hue } = get();

if (saturation < 0) saturation = 0;
if (saturation > 1) saturation = 1;
Expand All @@ -136,7 +174,12 @@ const createStore = () => {

if (value > 1) value = 1;

internalUpdateColor(chroma([hue, saturation, value, colorModel.alpha()], 'hsv'));
internalUpdateColor(chroma([hue, saturation, value], 'hsv'));

set({
saturation: saturation * 100,
brightness: value * 100,
});
},

updateByRgb: (rgb) => {
Expand All @@ -151,11 +194,14 @@ const createStore = () => {
);

store.subscribe((state) => {
const newHue = state.colorModel.hsv()[0];
const [newHue, newSaturation, newBrightness] = state.colorModel.hsv();
if (isNaN(newHue)) return;

state.hue = newHue;
state.saturation = Math.ceil(newSaturation * 100);
state.brightness = Math.ceil(newBrightness * 100);
});

return store;
};
const { Provider, useStore } = createContext<ColorPickerStore>();
Expand All @@ -169,32 +215,18 @@ export interface ColorObj {
hex: string;
}

export const colorSelector = (s: ColorPickerState): ColorObj => {
const [r, g, b, a] = s.colorModel.rgba();
const hsv = s.colorModel.hsv();
const hsl = s.colorModel.hsl();

return {
rgb: { r, g, b, a },
hsv: { h: hsv[0], s: hsv[1], v: hsv[2], a },
hsl: { h: hsl[0], s: hsl[1], l: hsl[2], a },
hex: s.colorModel.hex(),
};
};

export type SpaceColor = RGBColor | HSLColor | HSVColor;

export const colorSpaceSelector = (s: ColorPickerState): SpaceColor => {
const [r, g, b, a] = s.colorModel.rgba();
const hsv = s.colorModel.hsv();
const hsl = s.colorModel.hsl();

switch (s.colorMode) {
case 'rgb': {
return { r, g, b, a };
}
case 'hsv': {
return { h: s.hue, s: hsv[1] * 100, v: hsv[2] * 100, a };
return { h: s.hue, s: s.saturation, v: s.brightness, a };
}
case 'hsl': {
return { h: s.hue, s: hsl[1] * 100, l: hsl[2] * 100, a };
Expand Down

0 comments on commit 86923c8

Please sign in to comment.