I've been reading this book. Listening to this stupid podcast. It's been a year. I see an app icon with a skeleton on it. The skeleton is pointing up to the red notification badge on the icon. The number in the badge shows the number of weeks I have left. I decide to make an app about weeks and how we spend them and resolve to make it in a week so the effort reinforces the idea.
My sketches are super basic but still I find them useful when starting something new. Surprising details come out of the idea-to-paper translation, otherwise there's probably not much there. Having a sketch that captures the original idea can be real useful if you ever get lost during the design process.
At this point the app was just the icon. Icon design is not my strong suit (see sketches) but this was arguably the most important aspect of the app. Mexican imagery immediately came to mind, Harry Smith’s ‘Heaven and Earth Magic’ too. After a few attempts on paper I’m convinced that I can work out a sufficient skeleton drawing in Sketch.
Before I can put a number in the icon's badge, I'll need to get some information from the user: their current age and their age at death. I go with one question per screen and decide to use only standard iOS controls for speed and familiarity. I'm obsessed with black backgrounds (the true digital default) so I start there and begin adding type, then the button, then a control, then the different artboards. Working on the results screen leads to the arc shape.
I go for a walk, come back and see that I've gone off the rails a bit: the UI needs to visually support the theme of the app. I get rid of the red accent color and focus on drawing a few skulls and bones inspired by grade school Q-tip skeletons. I use the modular approach taken with the bone shapes and apply it to the other screens. After that the concept and the interface begin to gel.
With the visual elements in place, I took another look at the workflow. I realized that the first step "When were you born?" was overkill for the information I needed. Changing the question allowed me to get rid of the slider design and simplify it down to a single picker control.
With the design in place, I moved on to fleshing it out in Framer. I made use of the new Design tab (Summer, 2017) to lay out the artboards, titles and buttons. I'm looking forward to when you can wire up events and add components without leaving the Design tab, it's that nice of a layout tool.
Once I had the controls and the results screen in good shape, I handed the prototype to the people around me. My 7-year-old was frightened by the concept but was still able to understand and complete all the steps without coaching. UX success, concept still questionable.
Prototype vetted, it's time to build the real thing in Xcode. Because I believe in the future and this is such a simple view hierarchy, I try to do as much as possible through storyboards. First step is to embed the default project’s storyboard in a navigation controller. From there I drag in some view controllers, one for each Framer artboard, then create a new swift subclass for each so that I can customize them later. I drag in the PDF assets, add the ‘Next’ buttons and set up the navigation by ‘control + dragging’ from the buttons to the view controllers.
After figuring out how to style UIPicker, I then wrestled with getting my header labels right. Adding line breaks was having no effect. The solution ended up being setting the label’s line count property to 0 and then use ‘option + return’ to create the line breaks. Thank you Stack Overflow.
Now that the slider and the picker controls are sorted it's time to start the results screen. Borrowing from On the 8. I used CASpringAnimation
to match the prototype's animation. In Framer it’s trivial to get callbacks for any property change on any object. Core Animation, not so much. I naively assumed that there would be a progress property on the CAAnimation
that the view controller could observe. I ended up using a CALayer
subclass that adds a callback to its draw in rect
method. The solution was derived from these sources:
With that figured out, I then made the arc animations reflect the user input. Once I figured out the values for percentOfLifeLived
and percentOfLifeLeft
I started refining the spring animations and added timers to sequence the overlapping animations. I hope Interface Builder will support animation previews in the vein of IBDesignable
someday: having to recompile to see every timing adjustment felt cumbersome.
The open source physics engine I used in Amos has since been baked into SpriteKit. Adding the skull and bone assets to the physics simulation required zero code as it was all laid out in the Scene Editor, that was a nice surprise. I then added touch handlers to the objects in the scene and mapped the x
& y
gravitation constants to the device’s accelerometer. This means that when the app is opened and the phone is held upright the skeleton body will fall to the floor.
Time to move on to the blinking skull animation. I have a go at a keyframe animation in After Effects. That's working well and I'm reminded of Lottie. I wrestled with getting Cocoapods set up: remember to open the workspace, not the project. Once I had that rolling, Bodymovin and Lottie were a breeze to work with.
After finishing the info screen I took stock of the app and decided that the current age screen needed some kind of skeleton motif as well. I wanted to drive the current age visualization from the picker view. I decided on a literal representation of age: one bone is added to the screen for every year you’ve been alive. The bones are created and destroyed when the picker changes and the direction of the picker's movement influences the forces at play.
At this point the results screen seemed to entirely too dull. A missed opportunity. I added a third ring that’s constantly spinning to represent the passing of time. I extracted this out into a RotatingArcClass
and ended up using it three times.
The rings are nice but not enough. I wanted a full screen, 60fps visual effect for the results screen that spoke to what the information indicates. I quickly found Shadertoy and my way back to Spritekit beacuse of this post: Understanding Shaders in Spritekit. Here are the variables you'll need to convert to get a shader from ShaderToy working on iOS:
GlobalTime u_time iResolution size fragCoord.xy gl_FragCoord.xy fragColor gl_FragColor
No global vars, no in
or out
. It takes a bit of trial and error but the compiler messages helped quite a bit. After getting a flying-through-space-at-warpspeed effect to work I realized that it was the wrong visual. Not terrestrial or relatable enough. This screen should be grounded in a human perspective. I still like the infinity of the heavens motif as it implies something about the spirit. Thanks to this lovely example I ended up with an effect that reminded me of looking up at the night sky while in the mountains. There's more to do here, more serenity to add (like a dynamic moon that's in the correct phase or occasional birds passing by) but time was up for version 1. Here’s my final working shader:
void main() { vec2 i = gl_FragCoord.xy; float f = .5; float r = size.x; float t = u_time * .03; float c = cos( t ); float s = sin( t ); i = ( i / r - f ) * mat2( c, s, -s, c ); vec3 d = floor( f * r * vec3( i, f ) ); gl_FragColor = vec4( 1. / ( f + exp( 2e2 * fract( sin( dot( d * sin( d.x ) + f, vec3( 13, 78.2, 57.1 ) ) ) * 1e5 ) ) ) ); }
Here are the source files for this project, have at it. Created with Sketch 46.2, Framer v102, and Xcode 9.
Made by Justin Rhoades during the summer of 2017. 'How Many Weeks Left?' was last updated on 09.21.2017. This site was last edited on 09.24.2017. I do not mean to offend.