From ccea020e890ac2efad63c5530fa7aa316082da65 Mon Sep 17 00:00:00 2001 From: Ahmet Uysal Date: Tue, 19 Mar 2024 18:21:29 +0300 Subject: [PATCH 1/2] feat: add value as a prop --- src/index.tsx | 13 ++++++------- src/utils.ts | 3 +-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 7cebdb8..bfe3f51 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -10,11 +10,12 @@ export type ColorWheelProps = Omit, 'color'> & { color?: {hue: number, saturation: number, value: number}; defaultColor?: {hue: number, saturation: number, value: number}; onChange?: (colors: { hue: number; saturation: number; value: number }[]) => void; + value?: number } -export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, onChange, ...props }: ColorWheelProps) => { +export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, onChange, value = 1.0, ...props }: ColorWheelProps) => { const ref = useRef(null); - const [position, setPosition] = useState(defaultColor ? hsv2xy(defaultColor.hue, defaultColor.saturation, defaultColor.value, radius) : hsv2xy(0, 1, 1, radius)); + const [position, setPosition] = useState(defaultColor ? hsv2xy(defaultColor.hue, defaultColor.saturation, defaultColor.value, radius) : hsv2xy(0, 1, value, radius)); const harmony = useMemo(() => harmonies[harmonyName], [harmonies, harmonyName]); useEffect(() => { @@ -56,7 +57,6 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, const hue = rad2deg(phi); const saturation = r / radius; - const value = 1.0; const colors = harmony.map(harmonyHue => { let newHue = (hue + harmonyHue) % 360; @@ -69,7 +69,7 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, onChange?.([{ hue, saturation, value }, ...colors]); return colors; - }, [position, harmony, polar2xy, onChange, xy2polar, rad2deg, radius]); + }, [position, harmony, polar2xy, onChange, xy2polar, rad2deg, radius, value]); const drawCircle = useCallback((ctx: CanvasRenderingContext2D) => { @@ -91,7 +91,6 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, let hue = deg; let saturation = r / radius; - let value = 1.0; let [red, green, blue] = hsv2rgb(hue, saturation, value); let alpha = 255; @@ -104,9 +103,9 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, } ctx.putImageData(image, 0, 0); - }, [radius]); + }, [radius, value]); - const [r, g, b] = useMemo(() => xy2rgb(position.x, position.y, radius), [position, radius]); + const [r, g, b] = useMemo(() => xy2rgb(position.x, position.y, radius, value), [position, radius, value]); return (
{ +export const xy2rgb = (x: number, y: number, radius: number, value: number = 1.0) => { x -= radius; y -= radius; @@ -66,7 +66,6 @@ export const xy2rgb = (x: number, y: number, radius: number) => { const hue = rad2deg(phi); const saturation = r / radius; - const value = 1.0; return hsv2rgb(hue, saturation, value); } From 1633122f932b3209d7388060fc463fbbd7a45897 Mon Sep 17 00:00:00 2001 From: Ahmet Uysal Date: Tue, 19 Mar 2024 20:06:06 +0300 Subject: [PATCH 2/2] rerender circle when value changes --- src/index.tsx | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index bfe3f51..b364f57 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -18,6 +18,40 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, const [position, setPosition] = useState(defaultColor ? hsv2xy(defaultColor.hue, defaultColor.saturation, defaultColor.value, radius) : hsv2xy(0, 1, value, radius)); const harmony = useMemo(() => harmonies[harmonyName], [harmonies, harmonyName]); + const drawCircle = useCallback((ctx: CanvasRenderingContext2D) => { + let image = ctx.createImageData(2 * radius, 2 * radius); + let data = image.data; + + for (let x = -radius; x < radius; x++) { + for (let y = -radius; y < radius; y++) { + let [r, phi] = xy2polar(x, y); + + let deg = rad2deg(phi); + + // Figure out the starting index of this pixel in the image data array. + let rowLength = 2 * radius; + let adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array) + let adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array) + let pixelWidth = 4; // each pixel requires 4 slots in the data array + let index = (adjustedX + adjustedY * rowLength) * pixelWidth; + + let hue = deg; + let saturation = r / radius; + + let [red, green, blue] = hsv2rgb(hue, saturation, value); + let alpha = 255; + + data[index] = red; + data[index + 1] = green; + data[index + 2] = blue; + data[index + 3] = alpha; + } + } + + ctx.putImageData(image, 0, 0); + }, [radius, value]); + + useEffect(() => { if (!ref.current) return; const ctx = ref.current.getContext('2d'); @@ -28,7 +62,7 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, ctx.canvas.height = radius * 2 drawCircle(ctx); - }, []); + }, [drawCircle]); useEffect(() => { if (color) { @@ -71,40 +105,6 @@ export const ColorWheel = ({ radius, harmony: harmonyName, color, defaultColor, return colors; }, [position, harmony, polar2xy, onChange, xy2polar, rad2deg, radius, value]); - - const drawCircle = useCallback((ctx: CanvasRenderingContext2D) => { - let image = ctx.createImageData(2 * radius, 2 * radius); - let data = image.data; - - for (let x = -radius; x < radius; x++) { - for (let y = -radius; y < radius; y++) { - let [r, phi] = xy2polar(x, y); - - let deg = rad2deg(phi); - - // Figure out the starting index of this pixel in the image data array. - let rowLength = 2 * radius; - let adjustedX = x + radius; // convert x from [-50, 50] to [0, 100] (the coordinates of the image data array) - let adjustedY = y + radius; // convert y from [-50, 50] to [0, 100] (the coordinates of the image data array) - let pixelWidth = 4; // each pixel requires 4 slots in the data array - let index = (adjustedX + adjustedY * rowLength) * pixelWidth; - - let hue = deg; - let saturation = r / radius; - - let [red, green, blue] = hsv2rgb(hue, saturation, value); - let alpha = 255; - - data[index] = red; - data[index + 1] = green; - data[index + 2] = blue; - data[index + 3] = alpha; - } - } - - ctx.putImageData(image, 0, 0); - }, [radius, value]); - const [r, g, b] = useMemo(() => xy2rgb(position.x, position.y, radius, value), [position, radius, value]); return (