From 59a338da35a3910f580cfcdac7e574b542b6ca76 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 10 Jul 2023 18:15:33 +0800 Subject: [PATCH] doc: add README --- README.md | 16 ++++++++++++++++ src/App.ts | 4 ++-- src/models/Picture.ts | 5 ++++- src/models/reducer.ts | 2 +- 4 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ee4710d --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# Description + +A pixel editor allows you to edit pixel icon and export. + +The original idea and code structure is bought from [Eloquent JavaScript Chapter 19](https://eloquentjavascript.net/19_paint.html). + +I converted the code into TypeScript and expanded somehow in order to explore how to draw pixel in HTML canvas and how to manage states in vanilla way. + +It turns out the way to manage states in vanilla JavaScript(TypeScript) is quite "Reduxful" in which component dispatches actions, and reducer function caculates the latest state and notifies every component to sync the state(by calling component's syncState()). Component decides whether and how to update its own state when got notifies. + +The core elements of the way consists of: + +1. A state object of the whole App +2. A dispatch function passed down to each component to instruct it dispatch actions instead of handle events by itself. +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. +4. App component notifys every component to sync their state each time the reducer returns the newest state. \ No newline at end of file diff --git a/src/App.ts b/src/App.ts index 18b054c..cf7f749 100644 --- a/src/App.ts +++ b/src/App.ts @@ -9,7 +9,7 @@ import { draw, fill, rectangle, pick } from "./utils/drawHelpers"; import { EditorState, ActionObj } from "./types"; import Picture from "./models/picture"; -import { historyUpdateState } from "./models/reducer"; +import { reducer } from "./models/reducer"; const initialState: EditorState = { currentTool: "draw", @@ -44,7 +44,7 @@ function startPixelEditor({ tools, controls, dispatch(action: ActionObj) { - state = historyUpdateState(state, action); + state = reducer(state, action); app.syncState(state); }, }); diff --git a/src/models/Picture.ts b/src/models/Picture.ts index 1b15b96..03ba2d5 100644 --- a/src/models/Picture.ts +++ b/src/models/Picture.ts @@ -1,4 +1,7 @@ -// model for a frame of canvas +// Model for a frame of canvas +// The width is logical, eg. 16 X 16, not actual width of canvas element, which +// in app is hard-coded 384px +// When export canvas to image, the width should be used as actual width of the exported image. class Picture { public width: number; public height: number; diff --git a/src/models/reducer.ts b/src/models/reducer.ts index 98a612e..986b65d 100644 --- a/src/models/reducer.ts +++ b/src/models/reducer.ts @@ -1,7 +1,7 @@ import { EditorState, ActionObj } from "../types"; import Picture from "./picture"; -export function historyUpdateState(state: EditorState, action: ActionObj) { +export function reducer(state: EditorState, action: ActionObj) { if (action.type == "undo") { if (state.done.length == 0) return state; return Object.assign({}, state, {