owned this note
owned this note
Published
Linked with GitHub
# Shimmy: Flipbook Animation
## A Sketch-based flipbook animation tool
###### tags: `sketchdance`
Part of the [Sketchdance](https://hackmd.io/SIWsBN1UTNugwO6q3lMARg?both) project.
## Shimmy - Flipbook Animation
[Project Page](https://github.com/dethe/shimmy) on Github
[Shimmy Demo](https://dethe.github.io/shimmy)
*[Old Project Page](https://glitch.com/edit/#!/sd-shimmy?path=js/script.js:1:0) on Glitch*
*[Old Shimmy Demo](https://sd-shimmy.glitch.me/) on Glitch*
[Shimmy at RPL](https://launchpad.yourlibrary.ca/shimmy) in production, not always the latest version
[Twitch Stream](https://www.twitch.tv/RichmondPublicLibrary) Wednesdays 3-5pm pacific time. An hour of coding Shimmy, then an hour of using Shimmy
Intro/Outro music: [Zombies' March](https://opengameart.org/content/zombies-march) by Yd on OpenGameArt.
Background: <a href="https://www.freepik.com/vectors/background">Background vector created by upklyak - www.freepik.com</a>
## About
Shimmy aims to be an easy-to-use animation tool for children. It focuses only on sketching: there are no tools for drawing rectangles, ovals, or perfect lines. There is a single layer of onionskinning (trasparent previous frame) for aligning frames and a handful of tools to manipulate frames (copy, rotate, translate, zoom) and a small palette of colors (all colours are available, the palette gives quick access to a few).
Finished work can be saved as SVG (Shimmy's native format), animated GIFs, or PNG sprite sheets. For library use it is integrated with [Moat](/_x7d0oTFThGM3Q_DigDs7A) to allow users to access their work in library programs from home while ensuring user privacy.
Being web-based, Shimmy should be usable on desktop, laptop, and tablet computers. It hasn't been optimized for phones yet, but that should be do-able.
Shimmy is one part of the larger [Sketchdance Suite](/SIWsBN1UTNugwO6q3lMARg) of web-based interactive programs.

#### File Dependencies
Need to eliminate any loops in the dependency chart (Done, now confirm the rest of this is correct).
```graphviz
digraph hierarchy{
script -> file
script -> state
script -> ui
script -> frames
script -> tool
script -> dom
script -> animation
script -> stepper
script -> undo
animation -> dom
animation -> frames
animation -> state
tool -> dom
tool -> frames
tool -> state
tool -> ui
tool -> undo
file -> dom
frames -> state
frames -> undo
frames -> dom
frames -> ui
ui -> SVGCanvas
ui -> dom
ui -> palettes
}
```
### Timeline Dependencies
```graphviz
digraph hierarchy{
EVENT [color=green]
MODULE [color=red]
METHOD [color=purple]
"DOM REFERENCE" [color=blue]
script [color=red]
tool [color=red]
ui [color=red]
frames [color=red]
updateTimeline [color=green]
"updateThumbnail()" [color=purple]
"removeThumbnail()" [color=purple]
"thumbnailForFrame()" [color=purple]
"makeReferences()" [color=purple]
"addThumbnail()" [color=purple]
"toggleTimeline()" [color=purple]
"frameToThumbnail()" [color=purple]
".timeline-frames" [color=blue]
"body.notimeline" [color=blue]
"updateTimeline" -> script [label="notify listener"]
script -> "updateThumbnail()" [label="calls"]
tool -> updateTimeline [label="sends event"]
ui -> "makeReferences()"
ui -> "addThumbnail()"
ui -> "toggleTimeline()"
"makeReferences()" -> ".timeline-frames" [label="references"]
"addThumbnail()" -> ".timeline-frames" [label="references"]
"toggleTimeline()" -> "body.notimeline" [label="references"]
frames -> "addThumbnail()"
frames -> "removeThumbnail()"
frames -> "frameToThumbnail()"
frames -> "updateThumbnail()"
frames -> "thumbnailForFrame()"
}
```
Data model (as saved/restored)
**Update this!!!**
* name: filename
* tool: current tool name
* strokeWidth: current stroke width
* eraserWidth: current eraser width
* doOnionskin: t/f
* fps: current frames per second
* palette: selected index (not good, should be name)
* color: pen color
* bgcolor: background color
* color1-color8: color wells
* tab-file: t/f
* tab-draw: t/f
* tab-frames: t/f
* tab-animate: t/f
Other data (ui)
* currentMatrix
* currentDisplay: drawingboard/storyboard
* canvas
* currentFrame()
Things to test
* [x] esc to toggle UI
* [x] d to toggle display
* [x] ctrl-z for undo
* [x] ctrl-y for redo
* [x] n for new animation
* [x] ctrl-s to save
* [x] ctrl-o to open a file
* [x] g save as gif
* [x] p save as png
* [x] shift-1 pen
* [x] shift-2 rotate
* [x] shift-3 move
* [x] shift-4 zoom in
* [x] shift-5 zoom out
* [x] shift-6 eraser
* [x] shift-+ increase pen/eraser size
* [x] shift-- decrease pen/eraser size
* [x] 1-8 colors 1-8
* [x] shift-n add frame
* [x] shift-delete remove frame
* [x] shift-c clone frame
* [x] shift-x clear frame
* [x] shift-leftarrow first frame
* [x] leftarrow prev frame
* [x] right arrow next frame
* [x] shift-rightarrow last frame
* [x] k toggle onionskin
* [x] r play animation
* [x] Click palette to toggle UI
* [x] Show About
* [x] Show shortcuts
* [x] Toggle file, draw, frames, animate ribbons
* [x] New button
* [x] Load button
* [x] Save button
* [x] GIF button
* [x] PNG button
* [x] Switch between all tools with menu
* [x] Change pen size
* [x] Pen/eraser size should not go below 1
* [x] Palette changes from menu
* [x] Change colour
* [x] Change background colour
* [x] Choose from quick colours
* [x] Set quick colours
* [x] Add frame button
* [x] Remove frame button
* [x] Copy frame button
* [x] Clear frame
* [x] First/back/next/last buttons
* [x] Onionskin toggles with checkbox
* [x] Play button works
* [x] FPS takes effect
* [x] bgcolor maintained after playing animation
* [x] All custom settings, including colours, saved and restored in page reload
* [x] All custom settings, including colours, saved in SVG and restored on load
### Shimmy 2.0 Announcement
Major Features
• Eraser Tool! This was highly requested and is still a bit experimental, so I’m eager to hear feedback on it.
• Keyboard Shortcuts. If you are not on a tablet, these can really speed up using the app. For a full list of shortcuts select About Shimmy and then Keyboard Shortcuts.
Minor Updates
• Simplified undo/redo buttons. Because each frame has its own undo/redo stack, these were split between per-frame undo and document-wide undo (for things like adding or deleting a frame). Since only one document-wide action is not trivially undoable by other means, I got rid of all document-level undo except for Delete Frame, which is moved to a Gmail-like toaster notification (it pops up for a few seconds then goes away).
• Removed the Stop button. Animations are generally too short to need this, and I’m not entirely sure it was working. If people start making really long animations and ask for it then I can bring it back (and make sure it works).
• Named GIF and PNGs. Before these were just saved as “animation.gif” but now you can give them names. If you save the file as SVG, the name you used is saved, shown in the page title, and used as a default for GIF and PNG naming.
• Custom cursors. I can’t remember if this was in version 1, but it makes it a lot easier to see what tool you are using.
• Warnings before overwriting your file. New document and open document will destroy the current file. Now you are asked if you are sure so you get a chance to save if you haven’t already.
• Window resizing. If you started with a smaller window and made it bigger, you wouldn’t be able to draw in the full window. Now you can.
• And lots of bug fixes!
I hope you can try it out and let me know what you think! https://launchpad.yourlibrary.ca/shimmy/
I’m going to take a break on Shimmy for a while so I can work on Waterbear, but eventually I do want to add a few more features:
• Improvements to the color picker and palettes
• More flexible onionskinning
• A selection tool so you can manipulate just part of the page
• Copy/paste
• A timeline tool
• Gestures on touchscreens
• Parts (kind of like layers) so you can move specific named parts of the image independently between frames
• Save as Zip to save a folder of PNG files instead of all the frames in a single image
### Upcoming Features (& Bugfixes)

#### Cleanup I
* [x] Properly namespace all functions
* [x] Rely on module import vs. globals
* [x] Make each module expose only what's needed
### Cleanup II
* [x] Remove selection from drop-down on blur, it is interfering with keyboard shortcuts
* [x] Ctrl-O to open file, make popup making sure it is OK to overwrite the trigger for opening the file dialog.
* [x] Factor Moat integration into its own file
#### Improvements to the color picker
* ~~Checkout Farbtastic colour picker from Acko~~ (or not, it is big and requires jQuery)
* [x] UX: Improve color pickers, click anywhere outside color wheel to dismiss and set color of initializing button.
* [x] UX: Improve color pickers: update color on button during color wheel popup, add cancel button.
* ~~Azlen's idea for color picking:~~ https://mobile.twitter.com/azlenelza/status/1371961905154252801?s=19
#### Documentation
* [ ] Add back Config menus??? (Ugh, I hope not!)
* [ ] Document Using it as a storyboard tool
* [ ] Document 50 drawings challenge
* [ ] Document Tips and tricks
#### UX Improvements
* [x] Save name any time it is saved, file, gif or png
* [x] Use name in localstorage for multiple saves?
* [ ] Make app work offline
* [ ] UX: Handle orientation events: https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html#//apple_ref/doc/uid/TP40006511-SW23 (but maybe handling resize events covers this already?)
* [ ] UI: Desktop icon to save as app
* ~~UX: Show current frame while playing~~
* [x] UX: Add favicon.ico
#### Bugs
* [ ] Allow a video as background, for rotoscoping
* [ ] Implement all of the Community Building todos
## Beyond 2.0

* [ ] Share/embed
* ~~Control smoothing~~
* [ ] Control adaptive stroking (??? do I really want this?)
* ~~Show opacity control~~
* ~~Show patterns control~~
* [x] Use an underlying (immutable) model for UI
* [ ] Use an underlying model for drawing
* [ ] UI: Expose storyboard mode (??? is this useful)
* [ ] Background image and options
* [ ] Bug: Intermittent load failure on iOS
* [ ] UX: Move PNG generation to WebWorkers for performance
* [x] Track dirty state, prompt to save before overwriting
* [ ] Include demo animations
* [ ] Include tutorials
* [ ] Alternate layout: comic strip
* [ ] Zoom relative to drag distance?
* [ ] Eyedropper tool
* [ ] Print to flipbook
* ~~WONTFIX: Eraser (lines for now, test out masking as erasure)~~
* CANTFIX: Fix iOS Safari default zooming (pinch)
* WONTFIX: Bug: SVG size should be reset based on window size (only seeing this on one computer)
## Version Two
* [x] Move to Github ~~or Gitlab~~
* [x] Save/restore eraser size
* [x] UI: Custom cursors/pointers
* [x] UI: Remove "stop" button
* [x] Eraser undo
* [x] Why is eraser undo firing when I'm on the menus?
* [x] Why is currentEraserWidth 0 and not updating?
* [x] New Document warning
* [x] Doc undo still useful for Delete Frame - move to toaster popup
* [x] Undo Delete Frame hitting problem if first frame deleted, tries to insert after null sibling)
* [x] Undo Delete Frame having trouble restoring frame's undo/redo stacks
* [x] UX: Disable delete frame when there is only one frame
* [x] Bug: save as PNG (and display as storyboard) working on launchpad, but not in Glitch.
* [x] Bug: Open will overwrite current file without prompting
* [x] UX: Keypress handlers
* [x] Provide hints for keyboard commands
* [x] Allow naming file for gif download
* [x] Allow naming file for png download
* [x] Bug: Erase does not work on saved/restored images
* [x] Bug: Clear frame should be undo-able
* [x] Bug: Changing pensize/erasersize via keyboard only changes UI, not actual drawing size
* [x] Bug: Not getting toaster dialog for deleting frames
* [x] Bug: Throwing exception when using new frame from keyboard shortcut
* [x] Bug: Delete frame is not deleting
* [x] Bug: Deleted, then restored frame is onionskinned
* [x] Bug: Resize SVG on window resize (also on load, if necessary)
* [x] Design Bug: Undo should be self-initializing and lazy-initializing. Trying to use it before it is initialized is a huge source of errors.
* [x] Bug: Undo Erase erases line instead
* [x] UX: Shortcut keys for copy, paste, select all, delete, play, undo, redo
* [x] Title input
* [x] Shortcut keys for all operations (desktop/keyboard)
* [x] UX: Limit pen size to positive number
* [x] Link in "About": Keyboard shortcuts
## Version One
* [x] Step through creating some animations
* [x] Document production URL
* [x] Step-by-step to set up for a program
* [x] UX: Remove doc undo/redo, too confusing
* [x] Bug: Copying undo/redo stack doesn't seem to be working (*fixed* by removing UI)
* [x] Add About popup, show briefly at startup
* [x] Add logo/branding
* [x] What is this?
* [x] Limit creation of new points (smoothing as I go)
* [x] UX: Steve says a big limit is lack of eraser, need to fix that.
* ~~Possible approach: draw over, but fill with background~~
* [x] Better? Delete any points that intersect with eraser: change first point after interrupt to a moveTo vs. a lineTo (or make it a new path). [Design doc for eraser](/e6l8DU_zQN-TL6wS03HkRQ)
* [x] Important dialog options
* [x] Save (filesystem, Moat, Xastle, Gist)! (Ctrl-S to save as SVG, Ctrl-F to save frame as PNG, Ctrl-G to save as GIF, Ctrl-M to save as MP4)
* [x] Load (filesystem, Moat, Xastle)! (Ctrl-O to open SVG from file system)
* [x] Export GIF! (and GIF options)
* [x] Export PNG images!
* [x] Undo/Redo
* [x] Background color
* [x] Adapt toolbars to varying aspect ratios
* [x] Bug: Showing QR Code not working on iPad (Moat integration)
* [x] Bug: Download URL not working (Moat integration)
* [x] Don't show Moat integration if outside library network
* [x] Move files to launchpad server
* [x] Bug: sizing and layout in desktop browser
* [x] UX: Make touch targets bigger (at least on iPad). Colour wells and (especially) menu picking is just too small.
* [x] Reduce number of palettes
* [x] Replace Tool buttons with tool dropdown
* [x] Create dropdown
* [ ] Get icons working in options (there may not be a way to do this without using JS replacement for <select>)
* [x] Make sure tool selection works
* [x] Disable Pen-size control when pen is not selected
* [x] Make sure new/save/restore all work
* [x] Remove tool buttons
* [x] Undo/Redo
Development Note:
* Maps can have frames as key
* Three functions UndoPush, Undo, Redo. Can tell by type of undo object whether it goes to app stack or frame stack
* Keep an undo/redo stack for each frame, but not in the SVG, don't try to preserve undo stack across document loads.
* Frame-level undo-able events: draw, pan, rotate, zoom, clear
* Document-level undo-able: add/copy/delete frame
* [x] Add undo-redo buttons
* [x] If no items in undo stack, disable undo button
* [x] If redo stack has items, enable redo, otherwise disable
* [x] When a tool is used, clear redo, disable button
* [x] Add pushDocUndo/pushFrameUndo calls for all the methods
* [ ] ~~Should I ditch the distinction between doc and frame undo now, in anticipation of ditching it later?~~
* [x] Fix broken layout in desktop without breaking on iOS
* [x] Resize buttons so they don't overflow
* [x] Move toolbar show/hide buttons to be inline with toolbars
* [x] Separate out Frames from Animate
* [x] Put all tools in a drop-down? Or at least group together
* [x] Simplify palettes
* [x] Remove New from Draw toolbar
* [x] Move Clear to Frame toolbar
* [x] Re-test on iPad
* [x] Fix Delete and Add buttons
* [x] Bug: Pen Size widget breaks on iOS
* [x] UX: FPS Widget in Frames, should be in Animation
* [x] UX: Change frames buttons should be in Frames, are in Animation
* [x] UX: Load, Save, New need icons
* [x] UX: Load, Save, New should be grouped together
* [x] UX: Save as GIF, Save as Spritesheet should be 1/2 height, not 1/3. Or, WTH, just make them regular buttons?
* [x] UX: Change "pan" to "move"
* [x] Put stylii in box for Steveston
* [x] Button to hide/show all UI
* [x] UX: Moat: Show name of program on add_file page
* [x] Fix iOS Safari default zooming (double-tap)
* [x] Integrate Moat
* [x] JSON program list returned from Moat
* [x] JSON program list consumed by Shimmy
* [x] Create UI in shimmy
* [x] Fix CORS in upload
* [x] Upload file to Moat from Shimmy
* [x] Display file page on return
* [x] Fix information in file page
* [x] Save (as .shim svg, as .png, as .gif)
* [x] Figuring out the UI for file operations
* [x] Bug: Moat dates are not in UTC
* [x] Bug: Skipping a frame on Play
* [x] UX: Put cursor in first input (Moat)
* [x] Bug: Remove frame is broken (on Safari/iOS at least)
* [x] UI: Style label for select
* [x] Test GIF export
* [x] Fix GIF export
* [x] Bug Pen Color and Background not initialized? Not seeing the current color selected first time into color picker, but works OK later.
* [x] Bug: Rotate needs diff from original angle, or some further UI
* [x] Bug: Ctrl-* commands are used on Windows, maybe skip CTRL?
* [x] UX: Toggle views with same key?
* [x] UX: Clear all (new) vs. Clear Frame
* [x] UI: Stepper component
* [x] UX: Click selected tab to unselect, hiding toolbar
* [x] UI: Improve select for palette
* [x] UX: Save and restore state
* [x] Pen size and color
* [x] Background color
* [x] Tool selected
* [x] Toolbar selected
* [x] Palette
* [x] Colors in palette
* [x] Move framecount into animation toolbar
* [x] Bug: Buttons are round on iPad
* [x] Fix some minor layout issues
* [x] Bug: Logo overlaid on menu on iPad
* [x] Bug: Cannot draw outside of original rectangle after it has been rotated/scaled
* [x] Bug: After setting color, trying to draw fills background on iPad (pen size was larger than screen)
* [x] Make multiple toolbars displayable at one time
* [x] Don't hide them when showing another
* [x] Use flexbox for toolbar layout
* [x] Save and restore properly
* [x] Toggle the toolbar clicked, not the active one
* [x] Test on iPad
* [x] Bug: Pensize not working on iPad
* [x] Bug: Colorpicker popup not working on iPad
* [x] Bug: Clear doesn't clear background color
* [x] Bug: Re-center text and icons
* [x] Bug: Can't access controls under browser chrome on iPad
### MVP
It is very easy to get lost in the weeds on this project. What can I do to get what I had working before working on the web? I can iterate from there.
* [x] Rectangular buttons on iOS
* [x] Save/restore state (pen width, palette, colours, frame rate) Should I put this into the SVG or beside it? In the SVG is safest.
* [x] Converting to Canvas (for export and GIF)
* [x] Maybe a canvas/svg unified API for my limited needs (and for undo).
* [x] Still needs work on transforms
* [x] Evaluate current status
* [x] Fix buttons
* [x] New icons?
* [x] Use SVG
* [x] Pen color
* [x] Pen width
* [x] Next/Prev frame
* [x] Delete frame
* [x] Duplicate frame
* [x] Onion skinning
* [x] Play
* [x] Don't delete last remaining frame
* [x] Ignore right-click, ctrl-click, etc.
* [x] Zoom in/out
* [x] Rotate
* [x] Pan
* [x] Get transformed mouse coordinates
* [x] Ensure touch works
* [x] Frame rate
* [x] Turn onion-skinning on and off
* [x] Make sure click draws dot
* [x] Improve play experience
* [x] Reduce view to bounding box of animation + slight margin
* [x] Problem: hard to get bounding box when not visible
* [x] Restore across page reload
* [x] Make sure pen.cancel actually cancels
* [x] Alternate layout: storyboard
### Tools
* [Kelly Color Picker](https://github.com/NC22/HTML5-Color-Picker/wiki/Documentation) for colour picker
* Icons from [FontAwesome](https://fontawesome.com/icons?d=gallery&q=film&s=regular) and I have a license to use the pro version if needed
* ~~[Simplify](https://mourner.github.io/simplify-js/) a tool for simplifying (but not smoothing) lines.~~
* [Codepen demo](https://codepen.io/jacorre/pen/woyNXG) Smoothing, but not simplifying lines
* Steal line thickness by velocity from [Atrament](https://github.com/jakubfiala/atrament.js)
* GIF export using [Gif.js](https://jnordberg.github.io/gif.js/)
* Convert SVG to PNG (for GIF export) using [this script](http://bl.ocks.org/biovisualize/8187844) or any other means necesssary (maybe I can put the SVGs into image elements?).