Author
Travis Kirton

Estimated Time
10 - 20 minutes


The core focus of C4 is to make building beautiful interactive experiences and interfaces. C4 is centered around Apple’s Core Animation (CA) framework, and makes programming interactivity, animations and media way faster and way easier than working directly with CA.

This tutorial highlights the basics of getting media on screen and, in some case, playing. It is broken into self-contained examples so that you can jump to any section without having to read through the entire thing.

I built all these examples using the C4 Single-view template, that comes from the installer.

All of the examples below can be pasted into the setup() function directly in WorkSpace.swift.

For example, here’s how you can run the circle example:

override func setup() {
    let circle = Circle(center: canvas.center, radius: 50)
    canvas.add(circle)
}

Shapes

Shapes are all pretty straightforward: paths that you can style.

Squares & Rectangles

To create a square or a rectangle all you need to do is specify the frame into which it will be drawn:

let square = Rectangle(frame: Rect(0, 0, 100, 100))
square.center = canvas.center
canvas.add(square)

Circles

To create a circle you need to specify a center point and a radius:

let circle = Circle(center: canvas.center, radius: 50)
canvas.add(circle)

Ellipses

For anything that isn’t a circle, you specify the frame (just like a rectangle):

let ellipse = Ellipse(frame: Rect(0, 0, 200, 100))
ellipse.center = canvas.center
canvas.add(ellipse)

Lines

To create a line you need to specify a 2-element tuple (i.e. not an array) of Point:

let points = (Point(), Point(100, 100))
let line = Line(points)
line.center = canvas.center
canvas.add(line)

Lines are special 2-point polygons whose end points can be updated

Triangles

To create a triangle you need to specify a 3-element array of Point:

let points = [Point(), Point(100, 100), Point(200, 0)]
let triangle = Triangle(points)
triangle.center = canvas.center
canvas.add(triangle)

Triangles are simply 3-point polygons that close between the last point and the first point.

Polygons

To create a polygon you need to specify an n-length array of Point:

let points = [Point(), Point(100, 100), Point(200, 0), Point(300, 100)]
let polygon = Polygon(points)
polygon.center = canvas.center
canvas.add(polygon)

Regular Polygons

Creating a regular polygon, whose sides are all equal in length, is similar to creating a circle:

let regularPolyon = RegularPolygon(center: canvas.center, radius: 50.0, sides: 6, phase: 0.0)
canvas.add(regularPolyon)

The phase refers to the inital angle from which to start drawing the shape.

Stars

Creating a star is also similar to creating a circle:

let star = Star(center: canvas.center, pointCount: 5, innerRadius: 25.0, outerRadius: 50.0)
canvas.add(star)

Arcs

Creating an arc is similar to creating a circle, except you also need to add a start and end angle:

let arc = Arc(center: canvas.center, radius: 50, start: M_PI, end: 2 * M_PI)
canvas.add(arc)

Wedges

Creating a wedge is identical to creating an arc, except that it draws the pie-piece all the way down to the center point of the shape:

let wedge = Wedge(center: canvas.center, radius: 50, start: 1.25 * M_PI, end: 1.75 * M_PI)
canvas.add(wedge)

Text Shapes

You can create a text shape by specifying a string and a font:

let string = "C4"
let textShape = TextShape(text: string)!
textShape.center = canvas.center
canvas.add(textShape)

The TextShape initializer is optional because it depends on an optional font. So, you’ll need to handle it properly. Here, I know it will build properly so I force unwrap it with a !.

Colors

C4 has its own color object, and there are a ton of default colors and 3 of our own colors that we’ve cooked into the framework.

C4 Colors

The three default colors that we have in C4 are from the logo. There is C4Pink, C4Purple and C4Blue. Here’s how to use them:

let r = Rectangle(frame: Rect(0, 0, 100, 100))
r.center = canvas.center
r.lineWidth = 8
r.strokeColor = C4Blue
r.fillColor = C4Pink
canvas.add(r)
canvas.backgroundColor = C4Purple

Default Colors

There are a bunch of default colors cooked into C4. Here’s how to use a couple of them:

let r = Rectangle(frame: Rect(0, 0, 100, 100))
r.center = canvas.center
r.lineWidth = 8
r.strokeColor =  green
r.fillColor = blue
canvas.add(r)
canvas.backgroundColor = red

Check out Color.swift for all the default colors.

Custom Colors

Creating a custom color is pretty straightforward, you need to specify the RGBA components:

canvas.backgroundColor = Color(red: 0.25, green: 0.5, blue: 0.75, alpha: 1.0)

Pattern Colors

You can create colors from images too! Do it:

let r = Rectangle(frame: Rect(0, 0, 96, 96))
r.center = canvas.center
r.fillColor = Color("pattern1")
r.lineWidth = 8.0
r.strokeColor = Color("pattern2")
canvas.add(r)

Images

To add an image you simply specify the name of the file you want to use:

let image = Image("chop")!
image.center = canvas.center
canvas.add(image)

Filters

There are some nice filters that are already a part of C4. You can apply a filter to an image like this:

let image = Image("chop")
image?.center = canvas.center
canvas.add(image)

var dotScreen = DotScreen()
dotScreen.width = 10.0
image?.apply(dotScreen)

Generators

There are also image generators:

let image = Image()
image.frame = Rect(0, 0, 100, 100)

let checkerBoard = Checkerboard()
image.generate(checkerBoard)
image.center = canvas.center
canvas.add(image)

Notice that I didn’t use an optional here. This is because creating an empty image from a frame is always going to return an object. Unlike specifying a “fileName” that may or may not exist.

Movies

Like images, you can easily add movies to your apps by specifying the name:

let movie = Movie("halo.mp4")
movie?.center = canvas.center
canvas.add(movie)
movie?.play()

Unlike images, you need to specify the file extension of the movie.

Audio Players

Even though you specify the file name (incl. extension) creating an audio players is a little different than a movie. You need to create a variable outside the scope of the method you’re using to set it up:

let player = AudioPlayer("C4Loop.aif")

override func setup() {
    player?.loops = true
    player?.play()
}

When a movie is added to the canvas it gets a strong reference because it’s a subview of the canvas. Since an audio player is not a visible object to add to a subview, you need to store a reference to it as a variable.

Gestures

Compared to UIKit, adding a gesture is a cinch. In C4, every visible object is ready to have gestures attached to it, even the main canvas.

Tap

You can add a tap gesture to any object like so:

let square = Rectangle(frame: Rect(0, 0, 100, 100))
square.center = canvas.center
canvas.add(square)

square.addTapGestureRecognizer { locations, center, state in
    let randomColor = Color(red: random01(), green: random01(), blue: random01(), alpha: 1.0)
    self.canvas.backgroundColor = randomColor
}

Pan

You can add a pan gesture to any object. In this example, panning (i.e. dragging) on the canvas will update the position of the square:

let square = Rectangle(frame: Rect(0, 0, 100, 100))
square.center = canvas.center
canvas.add(square)

canvas.addPanGestureRecognizer { locations, center, translation, velocity, state in
    square.center = location
}

Animations

Almost every single object in C4 is animatable in one way or another. Visible objects have the most animatable properties, but others like AudioPlayers can also animate things like their pan properties.

In general, a good rule of thumb is:

If an object has a property, it’s probably animatable.

Properties

To animate something you create a ViewAnimation and put some code to change inside that object’s block. For example, the background property of any object (including the canvas) is animatable:

ViewAnimation(duration: 1.0) {
    self.canvas.backgroundColor = C4Blue
}.animate()

The previous block will immediately animate the background color to C4Blue, taking 1 second to do so.

You can also create the animation as an object, change its properties and animate it later, like so:

let anim = ViewAnimation(duration: 1.0) {
    self.canvas.backgroundColor = C4Blue
}

anim.curve = .EaseOut
anim.repeats = true

wait(1.0) {
    anim.animate()
}

Groups

If you have a bunch of animations that you want to start at the exact same time, you can do that by creating a ViewAnimationGroup:

let square = Rectangle(frame: Rect(0, 0, 100, 100))
square.center = canvas.center
canvas.add(square)

let circle = Circle(center: canvas.center, radius: 50)
canvas.add(circle)

let squareAnim = ViewAnimation(duration: 1.0) {
    square.transform = Transform.makeRotation(M_PI)
}

let circleAnim = ViewAnimation(duration: 1.0) {
    let randomColor = Color(red: random01(), green: random01(), blue: random01(), alpha: 1.0)
    circle.fillColor = randomColor
}

let group = ViewAnimationGroup(animations: [squareAnim, circleAnim])

wait(1.0) {
    group.animate()
}

Sequences

To execute a bunch of animations one after another you can use a ViewAnimationSequence:

let square = Rectangle(frame: Rect(0, 0, 100, 100))
square.center = canvas.center
canvas.add(square)

let circle = Circle(center: canvas.center, radius: 50)
canvas.add(circle)

let squareAnim = ViewAnimation(duration: 1.0) {
    square.transform = Transform.makeRotation(M_PI)
}

let circleAnim = ViewAnimation(duration: 1.0) {
    let randomColor = Color(red: random01(), green: random01(), blue: random01(), alpha: 1.0)
    circle.fillColor = randomColor
}

let sequence = ViewAnimationSequence(animations: [squareAnim, circleAnim])

wait(1.0) {
    sequence.animate()
}

Now You Can Build Anything

Shapes. Images. Movies. Audio. Gestures. Animations. These are the basics you’ll need to build any of the amazing iOS experiences you can imagine.

Grab of a copy of the the code from this tutorial: Basics Tutorial Code

Seriously. Complex interfaces and UI elements are all really just made up of these fundamental building blocks.