I’m a newbie here and in programming overall.
I am working on a project that resembles a pixel art editor using React + Redux and canvas.
I want to give the user the option to create and use their own color palettes that will be global for every drawing. Users can also create aliases for colors, e.g., “#4682b4” can be named “steel blue.” Additionally, I want to create a “default” color palette for each drawing. When a user uses a color from a palette, I add that color to the “default” palette. But I’m struggling with the implementation.
-
How do I handle switching between palettes?
-
How do I handle colors with the same hex but different names/palettes?
-
How do I handle replacing a color from one palette with a color in another palette?
-
How do I handle replacing a color in a palette that was used in dozens of drawings?
Perhaps I am overcomplicating things… How can I implement my idea or simplify it without discarding the idea of custom palettes?
Here is what I tried:
I created a ColorPalette component that render list of colors in this way
// ColorPalette component
return(
<div className="some-wrapper">
{colors.map(
(item: Partial<Palette>, colorIndex: number) => (
<ColorItem
index={colorIndex}
key={item.hex}
color={item as Color}
onDelete={() => onDeleteColorFromPalette(index, item)}
onUpdate={updateColorInPalette}
onSelect={onSelectActive}
active={activeColor === item.hex}
/>
))}
</div>
)
When user selecting drawing palette I use palette from EditorState, but when user switches to own palette I use UserPalettesState. Because of the different interface, I have to render the same component but with different event handlers.
// EditorPalette component
const EDITOR_PALETTE = 'editor';
const [paletteVariant, setVariant] = useState(EDITOR_PALETTE);
const userPalette =
paletteVariant === EDITOR_PALETTE ?
null :
userPalettes.find(({ id }) => id === Number(paletteVariant));
return (
<div className="some-wrapper">
<Select
value={paletteVariant}
onChange={(e) => setVariant(e.target.value)}
>
<MenuItem value={EDITOR_PALETTE}>
{i18n.projectsPalette}
</MenuItem>
{userPalettes.map((palette) => (
<MenuItem value={palette.id} key={palette.id}>
{palette.name}
</MenuItem>
))}
</Select>
{paletteVariant === EDITOR_PALETTE? (
<ColorPalette
palette={editorPalette}
onAddColorToPalette={addColorToEditor}
onDeleteColorFromPalette={deleteColorFromEditor}
onChangeColorInPalette={changeColorInEditor}
onSelectActive={setActiveEditorColor}
activeColor={editorPalette.active}
/>
) : (
<ColorPalette
palette={userPalette}
onSelectActive={setActiveEditorColor}
activeColor={editorPalette.active}
// other handlers doesn't work right now :(
/>
)}
</div>
);
// general interfaces
interface Palette {
id: number,
name: string,
colors: Color[],
}
interface Color {
id: number,
hex: string,
name: string,
}
// state of canvas
type EditorState = {
instrument: Instrument;
palette: {
active: string; // this is hex of the current active color
colors: Color[]; // this is list of colors from default palette
};
// ...other props
};
// state of user defined palettes
type UserPalettesState = {
data: Palette[];
loading: boolean;
}
But approach with two different states proved to be complicated. I also tried turn around interfaces to get a single list of colors. Like this
interface Color {
id: number,
hex: string,
name: string,
paletteId: number,
paletteName: string,
isActive: boolean,
}
But it’s doesn’t solve issue with duplicated hex values in different palettes. And somehow make switching between palettes even harder. What should I do?
P.S. Sorry for any mistakes in my English. I hope I described my issue correctly. ????
Qrisk is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.