Skip to main content
Clayzo plays documents natively on iOS and macOS through a Swift package. It draws with Metal, runs the same engine as the browser players, and takes the same documents and .clayzo bundles. There is no web view and nothing to fetch at runtime. Versions match the npm packages: clayzo-swift 0.3.6 plays what clayzo 0.3.6 authors and packages.

Install

In Xcode, choose File → Add Package Dependencies and enter https://github.com/Clayzo/clayzo-swift. Pick Up to Next Major from 0.3.6 and add the Clayzo library to your app target. In a Package.swift:
Xcode downloads the package and its engine once and verifies its checksum. No other tools, and nothing to install on your machine.

Play a bundle

Package the document with the CLI, add the .clayzo file to your app’s resources, and play it:
A bundle carries its fonts, images and audio, so this is the whole integration. The player sizes itself to the document’s aspect ratio and starts playing, looping, as soon as it appears. A document with audio starts muted; pass isMuted: false to hear it. See Bundles for what goes into one. You can also fetch a bundle over the network and pass the bytes to ClayzoBundle(data:); the file format is the same one the browser players load.

Play a document

A document with no fonts or images needs only its JSON:
For a document that references assets by id, register them yourself:
Font ids and image ids match the document’s asset ids. Register the fallback face as "*" for documents that name a font family without an asset. Fonts are registered once per app, not per player.

UIKit and AppKit

ClayzoPlayerView is the same player as a view you own:
Give the view the document’s aspect ratio; the document is scaled to fill it.

Interaction

Documents that declare interactivity respond to touch without any setup. A finger is the pointer: bindings follow it while it moves, a tap on a hit area is a click, and springs settle after it lifts. While a finger rests on an interactive document the player keeps the touch, so a drag drives the document rather than a navigation back-swipe or an enclosing scroll view. Turn isInteractionEnabled off for a player that should only be watched. Hit-area events arrive as they happen:
event.kind is enter, leave, down, up or click; hitAreaId and nodeId name what was hit. Declared inputs work as they do on the web:
A number input is clamped to the range the document declares. Values are .number, .boolean, .point(x, y) or .color(r, g, b, a).

Size and App Clips

The package adds about 1.4 MB to an app, so it fits comfortably inside an App Clip’s budget. Documents are separate: a bundle’s size is its images, fonts and audio. Package images at the size they are displayed rather than at their source resolution, and consider fetching bundles at runtime instead of shipping them in the clip — the limit applies to the installed clip, not to what it downloads.

What renders

Everything the WebGL player draws: shapes, paths, text, images, gradients, clips, mattes, blend modes, blur and drop shadow, glass, refraction, dithering, duotone, pixelation, mesh gradients and custom shaders — including shaders that call toLinearSrgb and fromLinearSrgb. Not yet: Lottie nodes and a second finger (the first touch is the pointer). Two things to know when authoring for phones:
  • The player renders at the view’s size in device pixels, so a document shown at 390 pt on a 3× display renders at 1170 px wide. A custom shader that mixes device pixels and document units renders differently at different sizes; see Things that bite for how to write one that scales.
  • A bundle with several font families uses the first as the fallback face for runs that name a family without an asset.