tl;dr — I wanted to learn how to use RelativeWave’s Form, so I broke an example down and created a few prototypes of my own.
These are my thoughts throughout the process.
First, some questions
What is Form?
Other tools create prototypes viewed in desktop viewers or mobile browsers. Form prototypes run natively on iOS devices using their viewer app, Form Viewer.
Do I need an iOS device?
For now, yes. There’s no way to connect it to iOS simulator. With the acquisition, I imagine Android support isn’t far off.
What background do you have with prototyping tools?
Form’s patch-based interface will be familiar to anyone who uses Quartz Composer and Origami. Unfortunately, that’s not me. This is my first foray into patch-based interaction design.
What’s in this post?
Most of this post is a breakdown of one of RelativeWave’s example files. After each section, I tried creating a prototype using concepts learned from that section.
Why did you write this?
I listen to the thoughtbot podcast often and something Ben Orenstein touches on is the idea that experts sometimes aren’t the best teachers. Someone fairly new to something has a better idea of what someone brand new to something is thinking. Experts sometimes lose that perspective.
I’m writing to solidify my knowledge while hopefully helping a future person who runs into similar issues early on.
The patch library allows you to browse all the patches. There are descriptions of patches here but I don’t think they’re documented online.
Pressing command + enter allows you to insert patch quickly.
At this point, I could add patches and connect outputs to inputs without any good sense of how anything works together. I thought I’d be able to get something somewhat interesting just throwing pieces together. Not so much.
Going through the tutorials
The Learn section has quick introductions to Form with short descriptions of features and videos showing how to use them. More thorough tutorials are in the Tutorials section on the Community page. The same tutorials are available on support.relativewave.com.
The tutorials are great for getting up to speed. I put them off a bit, instead working through some of the upcoming example breakdown. Then I stopped and went through the tutorials and they answered a lot of questions.
Quick early thoughts
- It’s nice to feel interactions right on the device. With Framer, we can get pretty close using browsers without UI chrome.
- On the other hand, it’d be nice to have a desktop viewer. For things like tweaking transition values, I won’t have to keep looking back and forth from desktop monitor to phone. I believe this is on RelativeWave’s roadmap.
- Form files work well with Git and GitHub for version control. OS X version control has also worked fine for reverting files.
- You can’t zoom in and out, but this was less of an issue than I thought it’d be. If things get to where this is a problem, it’s usually a sign that I need to start cleaning things up and grouping patches.
- You can’t ungroup things other than to go into the group, copy everything and paste it outside of the group.
- Switching apps closes the MacBook/iPhone connection, meaning you need to re-connect when re-opening the viewer on the iPhone. I disable iMessage notifications when prototyping.
- It’s really, really nice to just copy and paste objects from Sketch into Form. No need to export to a file and then drag and drop.
(These blue sections contain prototypes I built to try concepts out that I learned from the previous section. They’ll have links to the .form files on GitHub and short descriptions. I intended to have short screencasts breaking these down but didn’t quite have the time.)
Prototype One: Color View Bounce
The tutorials cover a lot more than this. But I wanted to create a sort of “Hello, World” prototype. This has a few color views that you can tap to bounce.
iPhone Map Photos by Parteek Saran
It’s great to be able to take a look at how other people approach problems. RelativeWave’s Examples section has Form files available to download and learn from. In programming, reading source code is a good step toward improving. Looking inside these Form files provides similar insight.
The example we’ll look at is by Parteek Saran (from the RelativeWave team) and is labeled iPhone Map Photos. Looks good, feels good. Here’s a look at the animation with the project file.
Looking at the project file, my first thought was, “That’s it?” As in: Cool, I thought there’d be more to it. Well, there’s more to it. I remembered you can group patches. So I took a look inside the two image groups:
My first thought was, “That’s it.” As in: Cool, I’m outta here. But I stuck around and it’s not so bad when looking at it piece by piece.
Image View (mostly the blue pulse)
Image Views are groups. This took some time for me to realize. This Image View is set to display the map. But it’s also a group containing 3 Image Views: Blue Pulse, Pin, and Pin Shadow.
Pin and Pin Shadow are both 2-patch combinations of an Image View and Image—this is the default combination when dragging and dropping an image into Form, as seen here:
Pin and Pin Shadow are straightforward. Blue Pulse is another Image View group. Let’s take a look inside.
Blue Pulse (Image View group)
I copied and pasted the blue pulse patches into a new file to get a pulse on the screen.
Here are some quick descriptions of the pieces—names provided by the user followed by patch types in parentheses.
Blue Pulse (Image View)
Image View patches actually render something on screen. The other patches help define what this patch displays.
This is the image file the image view displays. Again, dragging and dropping an image from Finder to Form gives you an Image View patch and Image.
Transition patches take numbers in and send scaled numbers out. We set the minimum and maximum output values.
As a reminder, “Scale” is just a user-provided name. We can change it to whatever name we feel like. This Transition patch modifies the Blue Image View’s scale so it’s a straightforward name. Right now, I’m thinking of transition patches as saying, “Make this input a variable.”
Another Transition patch. This one modifies the Blue Image View’s opacity. Minimum is 1 and maximum is 0 to fade to inverse things and fade out as the input value goes up.
This group has a single published output controlling the two Transition patches, making the pulse scale up every second while the opacity decreases every second.
It’s an interval timer—let’s see how it’s put together.
Pulse, an interval timer group.
Input Splitters take an input value and send the same value out, unmodified. At first, I couldn’t imagine why we would need this. But it makes sense now looking at this group.
As far as I can tell we can only publish outputs if the output is not connected to anything else. In this case, we want to publish the Stopwatch output, but it’s connected to the Conditional (>=) patch. We use the Input Splitter to publish an output for the group.
Conditionals compare inputs based on the operator you select and output true or false. Here, it checks if the Stopwatch time is greater than or equal to 1.
Unrelated to the “girls who wear Abercrombie & Fitch” band. Instead, it’s a low-frequency oscillation patch, allowing you to create different waveforms. Less catchy, more useful.
Here, it’s set to create a square wave, outputting a 0 or 1 and no values in between. This starts the stopwatch on a regular interval.
(State Input & State Output)
This combination took a little bit to understand. The State Input signal goes to the State Output signal. And neither patch is used to modify values.
Why can’t we just attach the output from the conditional straight to the Stopwatch Stop/Reset inputs? One answer that’s not really an answer: Form Viewer on my iPhone crashes immediately when I do that direct connection.
There’s a better answer in the State Tutorial on the RelativeWave Community site. They connect the State Input to the State Output with a Math patch in between. This combination creates an output that increments on each frame.
Outputs time values. Here, we stop/reset after every second.
Here’s a look at everything together with the values displayed.
The Stopwatch outputs time values between 0 and 1 second. That goes into the Conditional patch which outputs a bunch of NOs until the stopwatch outputs 1.0. Then it sends a YES to the State Input which is sent to the State Output. That sends out a YES once per second to the Stopwatch’s Stop/Reset inputs.
It seems like a lot to create an interval timer, but now we can re-use the Pulse group with an understanding of what’s going on inside.
You can double click connections to display values, but I learned that toward the end of writing this section. For a while, I was using the Console Log patch to view values coming from different outputs. This was tedious, unnecessary, and entirely my fault. (Near the bottom of this post, see Appendix A: Console Log, an Unexpected Journey.)
Prototype Two: Staggered Animation with Delay Control
This is another set of Color Views. I explored creating a staggered animation where you can set delay times. A single tap down signal is sent to multiple Springs, but Delay patches stagger the triggers.
Image Grid (Replicator group)
The Image Grid group is a Replicator. A Replicator creates copies of all the views inside its group. There’s a Replicator tutorial in the Form community section. The tutorial includes a link to a really good screencast by Laurel Wagstaff (from the RelativeWave team).
In this case, the Replicator creates four copies of the square photo.
Like before, let’s take a look at the different patches.
(Replicator Variables) — This gives us access to the index, position, and copies variables to use within the group. In my head, being inside a replicator group is sort of like being inside of a for loop.
Position is a value between 0 and 1—I think if we have 10 copies, it goes through 0.1, 0.2, etc. up to 1.
Rest (Input Splitter)—We saw an Input Splitter in the Blue Pulse group used to publish an output. Here, the Input Splitter publishes an input and forwards the input to the Transitions groups.
It’s been named Rest because it controls the rest value of the Springs in the Transitions groups. And it toggles between 0 and 1 on each screen tap.
X Position, Y Position, Opacity, Image (Multiplexers)—Multiplexers take a bunch of inputs and forward one input at a time based on an index value.
In this case, we’re taking outputs from the Transitions groups to properly set the Image View values. Here, the y position of each photo depends on the Transitions output:
You can also hard code Multiplexer source values. When the four photos move up and down, they move in a straight line and the x position never changes. The x position is hard coded in the Multiplexer:
Transitions (Group) and Images (Group) — Let’s take a look inside these two groups. We’ll start with Images.
The Images group is strictly organizational. The group contains a bunch of Image patches where each output is published. This gives us a nice single group to connect to the Image multiplexer.
There are two Transitions groups (one for y-position and one for opacity) and they look nearly identical inside.
Strength, Damping (Input Splitters)
Here, the Input Splitters have hard-coded values to connect to the Strength and Damping inputs of the Springs. This lets us have identical Springs without needing to change the values one by one every time.
Spring patches output values between 0 and 1. The Rest input is connected to our touch interaction so a screen tap triggers the spring.
Top Left, Top Right, Bottom Left, Bottom Right (Transitions)
Transition patches take values from 0 to 1 and scale them to fit min and max values. In this case we have the transitions set to our min and max values for y-position for one group and min and max values for opacity for the other group.
Something interesting that took a while to notice is that the Springs are all connected. The Position output of the first Spring is connected to second Spring’s Rest Input. We’re only actually triggering the first spring with the screen tap.
Very cool way to create a staggered effect. The values from the end of the chain (at the bottom) are slightly delayed compared to the start of the chain.
In Prototype Two, I also did a staggered transition. It was a different approach that allows you to set precise delay times for each transition.
Prototype Three: Image Grid and Camera Patch
Here I tried the Replicator out to see how it’d go automating the positions of a lot of items.
I also tried the Camera Preview patch. You can’t capture images but it’s still fun and something you can’t get with other web-based tools.
Back to the root view
Here again is the animation of the interaction along with the patches in the Root View.
The remaining patches handle the 3D effect where the map rotates backwards. Image Grid and Image View are faded since we’ve already taken good looks inside.
This Image is the dotted black and white map. It’s set as the image for the Image View that we took a look at earlier in this post. It’s worth mentioning again that Image Views are groups. The Image View showing the map is the parent and it contains the child Blue Pulse Image Views.
This Touch Interaction is connected to the Image View’s Interaction output and we’re only using the Down output. It makes the map a big tap target.
The switch is set to Toggle so each tap changes its output from YES to NO and vice versa. We took a look at this switch’s output in the previous section—it triggered all the Springs in the Image Grid Replicator.
Here in the root view, it’s also triggering a Spring.
This Spring is used on all four Transitions in the Transitions group. Each of the Transitions have identical animation curves and are triggered simultaneously.
This Transitions group is much simpler than the one we looked at in the Image Grid. The output from the root view Spring is connected to all the inputs. This triggers the Transitions at the same time, creating the map’s 3D effect.
In the following (somewhat lengthy) GIF, I removed the blue pulse and image grid. And I activate one Transition at a time to show how each Transition contributes to the total effect.
Y-Position: Starts at -20 and ends at 350, moving the map down.
Z-Position: Starts at 0 and ends at -500, moving the map into the background.
X-Rotation: Starts at 0 and ends at 55, rotating the map on the x-axis, creating the fall-back.
Scale: Starts at 1 and ends at 0.9, shrinking the map slightly.
That’s that. We’ve looked at pretty much every patch in the example. I hope it was helpful. Writing this out definitely helped me understand how things work.
More importantly, I think I get it now. Get it as in I think I know why people might prefer patch-based tools for this type of work, even if you can code.
Sketching interactions and modularity
The visual interface facilitates sketching interactions. Let’s connect this output to the z-rotation input and see what happens. That looks nuts, Cmd+Z, Cmd+Z, Cmd+Z.
It’s very cool how modular everything is. In breaking the example down, I was able to just copy things into a new project and they just worked. Prototypes let us test and learn. Then we toss them out and build for production.
It takes much longer to code clean, reusable components that approach the same level of modularity. Code, even throwaway code, has a feeling of permanence that I don’t feel when playing around in Form.
Code, flexibility, and permanence
There’s a Between Screens podcast episode with Scott Savarie where he discusses Quartz/Origami, Framer, and Objective-C.
That’s actually the best thing about Quartz Composer, in my opinion. The ability to play and try out many different interactions.
So each has a level of permanence. Scott discusses a spectrum where Sketch/Photoshop are at one end and working apps are at the other end. You become less flexible as you move from zero code to full code.
Presenting a bunch of static mocks is no problem. Presenting, say, five takes on an interaction with Quartz/Origami isn’t an issue. With Framer you become a little conscious of the overhead. And with Objective-C, the overhead would just be too much.
On this spectrum, Form sits right there with Quartz/Origami.
Back to prototyping—I’ll be sure to share what I’m making.
Console Log Patch, An Unexpected Journey
Console Log patches let you view values. A console viewer is on the Form roadmap, but we have to use other tools in the meantime.
The Form support site and a Facebook group discussion point to Apple’s iPhone Configuration Utility. That tool was recently deprecated. Now there’s the Apple Configurator, which apparently lets you view the device console. But I couldn’t figure that out either.
I Googled around and found an iPhoneConfigUtility.dmg file elsewhere — always exciting to download things from default Apache directory listings.
Last modified: April 2012. Why not? The console doesn’t seem to work. I’m guessing it’s a compatibility thing involving iPhone 6, iOS 8, and an older version of the Configuration Utility. But I also didn’t brick my phone or anything so that’s good.
After a bit more searching, I found iOS Console by LemonJar. Free and… it works! Here, I attached Console Log patches to the x/y values of the sampled touches. In the console you can see the changing values as I tap around
Then I read the manual. You can hover over connections to view live values. And you can double-click connections to add flags showing live values. Doh. Again: go through the tutorials—you’ll learn things like this right away.
But this might be useful in case you do need to use the Console Log patch.
Form Community Discussion Board
Form Support (Tutorials here are re-posted on the Discussion Board)
Form Examples and Demos
Form Community (Facebook Group)
Pasquale D’Silva — Contextual Zooming Interface Prototype
Pasquale D’Silva — Me being excited about Form