-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
16 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,16 +4,25 @@ A pixel editor allows you to edit pixel icon and export. | |
|
||
demo: [pixel-me](https://pixel-me.netlify.app/) | ||
|
||
## how to use | ||
|
||
1. git clone [email protected]:went2/pixelEditor.git | ||
2. cd pixelEditor | ||
3. npm install | ||
4. npm run dev | ||
|
||
## why wrote this project | ||
|
||
The idea and code structure originates from [Eloquent JavaScript Chapter 19](https://eloquentjavascript.net/19_paint.html). | ||
|
||
I converted the code into TypeScript and add some features in order to explore how to draw pixel in HTML canvas as well as manage states without any library. | ||
I converted the code into TypeScript and add some features to explore how to draw pixel in HTML canvas and manage states in a vanilla way. | ||
|
||
It turns out the way to manage states in JavaScript is quite "Reduxful" in which component dispatches actions, and reducer function caculates the latest state and notifies all components to sync the state. Component decides whether and how to update its own state and render when got notifies. | ||
It turns out the way to manage states in JavaScript is quite "Reduxful" in which component dispatches actions, and reducer function caculates the latest state then notifies all components to sync the state. Component decides whether and how to render when receiving latest state. | ||
|
||
The approach consists of: | ||
We need: | ||
|
||
1. A state object of the whole App | ||
2. A dispatch function which passes down to every component. When component's state changes, it dispatches actions instead of handle events by itself. Eg. | ||
1. A object containing all states of the application | ||
2. A dispatch function passed down to each component. When a component has some interactions with a user, it dispatches actions instead of handle events by itself. Eg. | ||
|
||
```ts | ||
class UndoButton implements UIComponent { | ||
|
@@ -31,12 +40,12 @@ class UndoButton implements UIComponent { | |
"⮪ Undo" | ||
); | ||
} | ||
// 3. The top App component will call every component's syncState with latest state. | ||
// 3. The root App component calls syncState with latest state. | ||
// Then each component updates its own state | ||
syncState(state: EditorState) { | ||
this.dom.disabled = state.done.length == 0; | ||
} | ||
} | ||
``` | ||
|
||
3. A reducer function(can be splitted into several) to caculate and return the newest state object based on the current object and action object. | ||
3. A reducer function(can be splitted into several) to caculate and return the newest state object based on the current object and action object. The implementation is in `/src/models/reducer.ts` |