Pablo - Image Editing App in Angular 2
The purpose of this article is to simply record what I learned in the process of using Angular 2 (RC1) while re-creating Pablo, Buffer's image editing web app.
Why Angular 2 & Pablo?
I'm very familiar with Angular 1 and I wanted to use Angular 2 as its architecture and performance are much improved. I believe these improvements will greatly impact my iteration and creation speed, something I'm always striving to enhance. Building Pablo is a way for me to test this theory while accomplishing some other goals.
I think Pablo's design and design aesthetic are well done and it seemed like an app with a relatively small scope that could also give me some different experience with
<canvas> and image filter effects. Combined, these are the reasons I chose to re-create Pablo as opposed to designing my own app from scratch (which I love to do). My main goal here was to focus on the development and code architecture as opposed to the visual design. Don't worry though, the visual design is on par with the original.
Angular 2 rocks. The overall architecture and the Angular Team's culling of numerous attribute directives in favor of a different binding syntax is great. In addition, the simplification of what a service is, is deeply appreciated. I also enjoy the explicit
Subject approach for eventing/communication. Overall, it was a joy to work in Angular 2 and I feel it provided me the ability to work quickly like I had hoped.
Part 1 of 2
I broke up the work for this web app into two parts. I broke it up this way to give me a bit more time to think about my approach for Part 2 as my gut was that this portion would be more difficult. It ended up being relatively straightforward, but there are still a few things to do to make it feature complete.
- Everything (including filters use) excluding
<canvas>overlay controls. ~32hrs
<canvas>overlay and editing controls. ~16hrs
Part 1 - Notes and Takeaways
- The Angular 2 CLI is awesome even in its early stage. The ng generate command is extremely useful for generating numerous files succinctly.
- Observables are interesting compared to Promises. It sounds like I may make better use of them in the future to decrease parent-to-child view binding.
.apply()and JSON to create a really flexible way to apply image filters.
- Wrote IndexOfPipe and learned about the advantages and disadvantages of it and related solutions.
EventEmitters are for child to parent communication and
Subjectare for communicating via services and components.
Part 2 of 2
This part was pretty cool as I haven't created a lot of editing tools like this. Though I still have some things to do (todos below), I think it turned out pretty slick.
Part 2 - Notes and Takeaways
@ViewChildrenare best practice ways for succinctly gaining reference to children.
- Through an Observable in my
EditSettingsServiceI was able to easily update the edit controls parent and sync the model to edit.
- You can use
Subjectto allow default values at startup.
- If you give a
tabIndexvalue it can accept key events. This is how I implemented the nudge capability using the arrow keys.
I have the core of the filters functionality working, but I had to comment it out as the current build process fails with the third party image editing tool Caman.js that I'm using.
In fact the Angular-CLI I'm using won't currently build successfully at all for me (very alpha stage so I'm not worried). As a result though the app link below is a non-production build and thus will download slower than the production build will. It builds now - May 23. That said, it should run well. I've only worried about this working in Chrome due to the core goals of this exercise.
- Reposition photo functionality
- Fix filters (proper build and apply only one with reverting previously applied filter)
- Resize handles and multi-line header, body, and caption texts
Load logo image, not just dummy placeholder~30min - May 19
- Subtle UX tweaks (initial pos of edit texts, templates, etc)
In the process of experimenting with Angular 2 to re-create Pablo, I noticed a few things that may improve the original. In no particular order here are a few notes:
- Make selectable items overlaying the canvas nudgable via arrow keys (possibly shift + arrow keys for incremental nudge)
- Delay loading fonts as they're relatively heavy and may never be used. This may speed up app initialization time.
- On first load, simply clicking the Shuffle button a few times quickly breaks the image selection. In fact clicking the Reposition button shows that multiple images are present.
- Use of or better use of
user-select: none;to prevent unwanted highlighting of buttons and controls during dragging/editing may be useful.