Browser based Pixel Editor for creating pixel assets or fonts.
- Editor
- Self contained React drawing canvas.
- Application
- Work in Progress Features
- Eraser (pen erasers work on tablets)
- Shapes (Line, Rect, Circle)
- Cache state to
localStorage
to persist changes
- Work in Progress Features
Majority of the functionality lives in the Editor
component.
Any contributions or updates to the Editor component must be self contained.
width
- Image widthheight
- Image heightsize
- Grid sizeonChange
- Get the path data on change.
Note:
onChange
criteria for triggering:
- 1 second after any concurrent drawing.
- Instantly after undo/redo actions.
getJson: (includeHistory: Boolean) => string
setJson: () => void
getVersion: () => number
addColor: (color: EditorColor) => void
updateColor: (index: number, color: EditorColor) => void
removeColor: (index: number, mergeIntoIndex: number) => void
moveColor: (fromIndex: number, toIndex: number) => void
getColors: () => EditorColor[]
clear: () => void
clearHistory: () => void
getHistory: () => []
setMeta: (property: string, value: string | number | Boolean ) => void
getMeta: (property: string) => string | number | Boolean
getMetaProperties: () => Object
applyTemplate: (data: number[][]) => void
flipHorizontal: () => void
flipVertical: () => void
translate: (x: number, y: number) => void
rotate: (counterClockwise?: boolean) => void
invert: () => void
undo: () => void
redo: () => void
hasUndo: () => boolean
hasRedo: () => boolean
inputModePixel: () => void
inputModeLine: () => void
inputModeRectangle: () => void
inputModeRectangleOutline: () => void
inputModeEllipse: () => void
inputModeEllipseOutline: () => void
import Editor, { EditorRef } from '@pictogrammers/editor';
function App() {
const editorRef = useRef<EditorRef>(null);
const width = 22;
const height = 22;
const size = 10; // Grid size
function handleChange(path: string) {
console.log('Path:', path);
}
function handleClear() {
editorRef.current?.clear();
}
return (
<Editor ref={editorRef}
width={width}
height={height}
size={size}
onChange={handleChange}></Editor>
<button onClick={handleClear}>Clear</button>
);
}
export default App;
The data
grid stores each pixel as a reference to the colors array. A diagonal line in a 3x3 canvas would look like below.
data = [
[0, 0, 1],
[0, 1, 0],
[1, 0, 0]
]
See the helper methods above for all the quick operations for modify the data grid.
The data
grid stores each pixel as a reference to the colors array. For example 1
in the data grid would be the 2nd item in the colors array. The color object looks like below:
type Color = {
r: number; // Red 0 to255
g: number; // Green 0 to 255
b: number; // Blue 0 to 255
a: number; // Alpha 0 to 1
name: string; // Friendly name
}
The default colors
array then looks like below:
colors = [
{ r: 0, g: 0, b: 0, a: 0, name: 'transparent' },
{ r: 0, g: 0, b: 0, a: 1, name: 'Black' }
]
To ensure the indexes in the data
grid stays in sync with the colors
array the helper methods below are provided.
getColors: ()
- Get an array of colors
addColor: (color: EditorColor)
- Add a new color to the end of the array.
updateColor: (index: number, color: EditorColor)
- Update the color value.
removeColor: (index: number, mergeIntoIndex: number)
- Removing a color requires selecting an existing color.
- This operation throws an error for less than 2 colors.
moveColor: (fromIndex: number, toIndex: number)
- Swap the position of 2 colors.
mergeColor: (fromIndex: number, toIndex: number)
- Merge one color into another. This is only supported with more than 2 colors.
Note: All color operations are added to the canvas history.
All operations that change the canvas or meta data create change records in the history.
- Pixel - Single color change on the canvas.
- After 1 second or any other canvas operation is called.
{ type: 'pixel', value: [] }
- Undo -
{ type: 'undo', value: 2 }
- Redo
- Decreases the Undo
value
by 1 if it is the last history value.
- Decreases the Undo
- Clear
{ type: 'clear', value: { data: [] } }
- Width / Height
{ type: 'width', value: { from: 22, to: 24, data: [] } }
{ type: 'height', value: { from: 22, to: 24, data: [] } }
- Note: Resizing canvas takes a snapshot of the canvas prior to resize
- Color
{ type: 'addColor', value: EditorColor }
{ type: 'removeColor', value: index }
{ type: 'updateColor', value: EditorColor }
{ type: 'moveColor', value: EditorColor }
{ type: 'mergeColor', value: { from: 2, to: 1 } }
- Meta - Any change that impacts meta data.
{ type: 'meta', value: { name: 'Foo', _name: 'Bar' }}
The application can modify the history log through the helper methods:
undo()
- Undoredo()
- RedohasUndo()
- Has at least 1 item in the historyhasRedo()
- Last history record istype: 'undo'
setMeta(property, value)
- Only supports adding meta data.{ type: 'meta', value: { property: value, _property: value } }
- The
_property
is the previous value ornull
- Setting a
null
value removes the property.
getMeta(property)
getMetaProperties()
- Properties object.getHistory()
- Retrieves entire history log.clearHistory()
- Clears the history