Close
Simone Seagle

Simone Seagle

Independent Web and Educational Software Developer

Read More

Search

Prev
An (Animated) Edward Lear Alphabet
Projects

An (Animated) Edward Lear Alphabet

May 20, 2020 Simone Seagle

The Edward Lear Alphabet is an interactive e-book-like celebration of an Edward Lear alphabet poem from 1871. I used public domain artwork to create a unique animated illustration for each letter of the alphabet and then wrapped the whole thing up in a Vue.js application for deployment.

A was once an Apple Pie

A was once an Apple Pie.

Project Setup

This quarantine time allowed me to take on a project that I've wanted to do for a very long time. The idea sprouted when I borrowed this book from the library and had one of those weird flashbacks when you remember something from your childhood. (Ever experience those? They're weird.) I really enjoyed reading the book out loud to my children, and I wanted other kids to have the same fun. By this time, I had already made a few of the animated artwork pieces, and knew at some point I wanted to do an animation for each letter. I debated with just adding them one by one to my website, but that seemed really inefficient because I wanted people to be able to easily go from one to the next.

From there I decided that it should be its own server and run as a web app. I started out running it like a regular Vue app, but I found that it was really annoying to go from one letter to the next, and I had to go through a whole spiel every time I added a new letter animation. Seemed like a job for Vue Router so I installed it. But a word of warning - when I installed Vue Router, it wiped my whole App.vue file! Fortunately all of the important animation work was in a different file, so it didn't really set me back too far. Totally worth it, because the navigation for the app was way better afterward.

G was once a Little Goose

G was once a Little Goose.

Animations and User Interface

I made the animations much the same way I've done other ones. I used Photoshop to cut apart the piece of art that I selected for the letter, and then thought about how I wanted each piece to interact. Then, I stored the file names and info about every sprite and letter in a massive JSON file. Rather than doing a completely new animation for each letter, I used what I learned from previous animated art pieces to create a list of 13 different behaviors (swing, teeter, follow, point, spin, etc...). I assigned the appropriate frame update function to the sprite so I could keep the frame update code very simple. To keep them from looking too uniform, I could assign different speeds, offsets, and other parameters. Then, as in other projects, I used PIXI.js to handle moving the sprites around. For example, here's my update code for the "point" behavior where something orients at the interaction point. (See it in action in the prawn's antennae)

    // This gets assigned to the sprite as just generic "interact"
    point: function(sprite){
        // Transformed point is the touch point transformed to local art coordinates
        if (this.transformedPt.x >= 0) {
            // The angle from the sprite to the pointing location
            sprite.targetAngle = Math.atan2(this.transformedPt.y - sprite.y, this.transformedPt.x - sprite.x);

            // In case we don't want it to spin the whole way around
            if (sprite.targetAngle > 0) sprite.targetAngle = Math.min(sprite.targetAngle, sprite.angleRange[1]);
            else sprite.targetAngle = Math.max(sprite.targetAngle, sprite.angleRange[0]);
        } else {
            // When no one is interacting with it, we want to occasionally give it a little boost so it doesn't all get too still
            if (Math.random() < 0.01) {
                let spread = Math.max(...sprite.angleRange) - Math.min(...sprite.angleRange)
                sprite.targetAngle = Math.min(...sprite.angleRange) + Math.random() * spread;
            }
        }

        // Use spring physics to "spring" the angle.
        sprite.speed += this.updateVelocity(sprite.rotation, sprite.targetAngle, sprite.speed, 0.008, 0.05);

        sprite.rotation -= sprite.speed;

        // We continuously check the sprite versus its home location in case of mobile mode where you can pan back and forth in the x-axis
        sprite.x = sprite.home.x * this.scale + this.panOffset;

    },
    // Standard damped harmonic oscillator formula that I use a ton
    updateVelocity: function(j, targetJ, vJ, k, dampCoeff) {
        var spring = k * (j - targetJ);
        var damp = -dampCoeff * vJ;
        return spring + damp;
    },

For the UI design I reached out to Haley Wakefield. I knew that I wanted this project to not look like something I'd just thrown together, and good UI is really non-negotiable. One important way that she helped was in the mobile accessibility. I've had issues with that for a while because I feel like art should be big, and it hadn't interested me much to deal with mobile phones. Obviously that's not a smart move in 2020's mobile-first development, so she came up with the idea to have the landscape art be able to pan on phones. This worked really well and wasn't as hard to implement as I thought it would be. Rather than using responsive CSS to pull it off, I used the PIXI.js rendering and just offset the sprites when someone used a panning gesture.

K was once a Little Kite

K was once a Little Kite.

No-Loading-Screen Loading!

One of the most satisfying parts of programming this project is something no one is ever likely to notice. When I first started working on it, I had all the sprites load as soon as you got to the main screen, but I quickly realized that was terrible. Not everyone might even want to go through the whole alphabet, and I would have forced them to load 40+ MB of content. What if someone saw the loading screen and then bounced because loading screens are lame? Granted, you need them sometimes, but I think they should be a last resort. SO - I came up with a slick implementation of lazy loading.

When someone arrives at the home screen, I only load the assets for 'A', because that's where the big 'START' button leads. It loads in the background, so should not hold anyone up. If you go to A, it will load 'B' while you're reading 'A', and so forth. If you use the letter menu, it will load the letter you picked plus the two adjacent letters to that one. So for example if you pick 'R', it loads 'Q' and 'S'. This way you only get the hourglass for the first letter and it should load slowly in the background only grabbing what you need.

Launching and Lessons

From the project beginning to project launch, this took less than 8 weeks! Turns out if my computer is sitting on the kitchen counter I putz around with that instead of my phone! I also received money from New Mexico's Self-Employment Stimulus Package which I was able to use to pay Haley, buy the domain, and pay for hosting.

Hosting was a fun adventure because I gave AWS Amplify a shot, but I couldn't make it work with my domain, which is held by GoDaddy. It took me three hours and mostly bad things happened, and I would have had to pay $30 to get help, as far as I could tell. Finally, I went to a local hosting company, Lobo Internet. This was the way to go from the start, I think. I was using state money to pay for the hosting, so why not keep the money local and going to a place that really needed it? Turned out it was an awesome choice because I DID NOT have to pay money to get help from a human being. Turns out the humans there are wonderful and were able to help me when I (humble brag alert!) burned through my entire bandwidth in the first two days after the project was launched. (:

If you haven't yet, please give the Edward Lear Alphabet a try!