A diagram drawing application which is demonstrating how we can utilize React.js
and HTML <canvas/>
to create an interactive drawing.
https://draw.crispyscript.com (works best in desktop)
Demo.mp4
- Line drawing tool
- Rectangle drawing tool
- Pencil drawing tool(free-hand)
- Selection tool for moving and resizing a single element
- Undo/Redo/Clear
- Text tool
- Support deleting a selected element
- Arrow drawing tool
- Pan
- Zoom
- CSS & Styling
- Mobile & Resizing friendly
- Multi-select elements
- Support uploading an image
- Duplicate elements
- Send to back/front
- Save the result to file / local storage (need to serialize the image)
- Limit max history stack to ~50 items
- Export canvas to png/jpeg
- Rotate
- Keyboard shortcut
- Setting stroke color
- Setting stroke width
- Filled rectangle
- Copy & Paste elements (upgrade "Duplicate" feature)
- Run
yarn
to install all dependencies - Run
yarn start
to start the app locally
- Run
yarn visual:test
to do regression test - If there is any failed test, investigate it one-by-one by going to
./cypress/snapshots/diff
directory. - After a specific test file is fixed. To override all base screenshots of that file, run the following command.
# We want to override ALL screenshots for test-file.spec.js file yarn cypress run --env type=base --config screenshotsFolder=cypress/snapshots/base,trashAssetsBeforeRuns=false --spec "cypress/integration/test-file.spec.js"
- Repeat step 2-3 until
yarn visual:test
results all passed. - Only after all tests are passed, clean up all existing screenshots and re-create them from scratch by running
yarn visual:dangerously-override-all-base
. Note that, this command is dangerous since you will lose all existing screenshots.
Note: Tests may fail due to OS difference. All base screenshots are created on Macbook Pro 13".
More info: cypress-visual-regression Doc
The following functions are temporary. Mostly use for debugging. In the future, we will implement a proper export/import feature.
exportSnapshot()
to export the diagram (must not have any image element)importSnapshot(value)
to import,value
is the result of callingexportSnapshot()
(must not have any image element)
- Most of x, y value are in
scene
coordinate (i.e. canvas coord, not viewport coord). They are inconsistency in naming. For example,// All of these variable names are in `scene` coord let sceneX, x1, x2, pointerX
- However, the
viewport
coordinate is more consistency in naming.// There always be `viewport` keyword in `viewport` coord let viewportX