Embedding assets with Spine Web Player

April 6th, 2020

Sometimes, all you want in life is a simple .html file that contains all the assets needed to show off your fine Spine skeleton, its animations, and its skins. No pesky web servers required. Just double click the .html file and your browser will show your beautiful art.

We've added this capability to Spine Web Player and by proxy spine-ts and all its backends for WebGL or Canvas! Let's see how it's done.

Data URIs - Preparing your assets

When you want to tell your browser to load an asset, like a .png file, you specify an URL, for example:

<img src="https://mydomain.com/images/myimage.png">

Or a relative URL, for example:

<img src="/images/myimage.png">

When the browser encounters such a URL, it asks the server to send the data for that file.

We need to find a way to avoid talking to the server at all. Thankfully, modern browser standards give us a tool to do just that: data URIs.

A data URI is a long text that starts with data:, followed by a MIME-type, followed by the actual data of the file. The data itself is Base64 encoded. This way, even binary data can be safely dumped into an HTML file.

To convert a file to a data URI, we can use one of the many data URI encoders. The basic principle is always the same:

  1. Specify a file or URL to a file.
  2. Click "Upload" or "Encode" or whatever button is shown.
  3. Copy the data URI text.

I did just that for the atlas page of our Raptor example, which is located at http://esotericsoftware.com/files/examples/3.8/raptor/export/raptor-pma.png. Using this HTML element:

<img src="http://esotericsoftware.com/files/examples/3.8/raptor/export/raptor-pma.png">

We end up with this nice image:

raptor

If we used the data URI version of the file, the tag would look like this instead:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhE....">

Note that I cut off most of the data URI above, as it's very long. The size is the price to pay when we want everything to be embedded in a single .html file.

Now that you know about data URIs, it's just a few steps to get your exported Spine assets prepared for embedding:

  1. Open your Spine project in Spine and export the skeleton data to .json or .skel, and your atlas to a .atlas and one or more .png files.
  2. Encode each file with the data URI encoder and store each resulting texts somewhere, e.g. a file or temporarily in a text editor of your choice.

That's it! You are now ready to embed your assets together with the Spine Web Player.

Setting up the Spine Web Player with embedded assets

We've previously discussed the Spine Web Player on this blog. If you are rusty on the details, I suggest you quickly head over to that blog post and refresh your memory.

Here's a basic .html file that uses the Spine Web Player to display the Raptor:

<script src="https://esotericsoftware.com/files/spine-player/3.8/spine-player.js"></script>
<link rel="stylesheet" href="https://esotericsoftware.com/files/spine-player/3.8/spine-player.css">
<div id="player"></div>
<script>
new spine.SpinePlayer("player", {
jsonUrl: "https://esotericsoftware.com/files/examples/3.8/raptor/export/raptor-pro.json",
atlasUrl: "https://esotericsoftware.com/files/examples/3.8/raptor/export/raptor-pma.atlas",
animation: "walk",
backgroundColor: "#666666",
});
</script>

We can see that we tell the player to load 2 files: raptor-pro.json and raptor-pma.atlas. When the player reads the .atlas file it sees that it also needs to load another file, raptor-pma.png, the image making up the first (and only) atlas page.

All these files are loaded from our servers. To avoid that and instead keep everything in a single .html file, we can use the new configuration property rawDataURIs. I have converted the files raptor-pro.json, raptor-pma.atlas, and raptor-pma.png to data URIs as described in the last section. Next I rewrote parts of the script above:

<script src="https://esotericsoftware.com/files/spine-player/3.8/spine-player.js"></script>
<link rel="stylesheet" href="https://esotericsoftware.com/files/spine-player/3.8/spine-player.css">
<div id="player"></div>
<script>
new spine.SpinePlayer("player", {
jsonUrl: "raptor-pro.json",
atlasUrl: "raptor-pma.atlas",
rawDataURIs: {
   "raptor-pro.json": "data:application/json;base64,ewoic2tlbGV0b...",
   "raptor-pma.atlas": "data:application/octet-stream;base64,CnJhcHRvc...",
   "raptor-pma.png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU..."
},
animation: "walk",
backgroundColor: "#666666",
});
</script>

I have again cut off the data URIs in the above snippet as they are super long. Let's see what we changed.

First, we rewrote the jsonUrl and atlasUrl properties. Instead of specifying a full URL, we just specify a file name (relative paths). Next, we added the rawDataURIs property. It consists of "filename": "data URI" pairs, one for each file we need to load and render the raptor. That's it!

The Spine Web Player will then try to load the jsonUrl. Since the raptor-pro.json data is given in the rawDataURIs property, the player takes the data directly from there instead of asking a server to provide it. The same happens for the raptor-pma.atlas file. When the atlas file is loaded, the player sees that the atlas needs the image raptor-pma.png. And since we specified that in rawDataURIs as well, there is not a single request to a server, except for the player JavaScript and CSS, which you can also embed.

Of course this also works with binary skeleton data:

<script src="https://esotericsoftware.com/files/spine-player/3.8/spine-player.js"></script>
<link rel="stylesheet" href="https://esotericsoftware.com/files/spine-player/3.8/spine-player.css">
<div id="player"></div>
<script>
new spine.SpinePlayer("player", {
skelUrl: "raptor-pro.skel",
atlasUrl: "raptor-pma.atlas",
rawDataURIs: {
   "raptor-pro.skel": "data:application/json;base64,ewoic2tlbGV0b...",
   "raptor-pma.atlas": "data:application/octet-stream;base64,CnJhcHRvc...",
   "raptor-pma.png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEU..."
},
animation: "walk",
backgroundColor: "#666666",
});
</script>

Instead of using the jsonUrl property, we use the skelUrl property. In the rawDataURIs section we specify the data URI for the .skel file.

Binary skeleton files are quite a bit smaller on average than their corresponding .json files, so use binary skeleton files if possible.

Note: When embedding data URIs for skeleton .json or .png files, your editor of choice might freeze a little or be sluggish because the lines are so long. Turning off line wrapping may help. An alternative solution is using an editor like Sublime Text or Visual Studio Code, which work well even with long lines.

Up next

We'll include a new export option in the next version of Spine, giving you a one click solution to do all the above. The end result will be a .html file you can open from disk with any web browser. This way friends and co-workers to easily view your work. Stay tuned and keep an eye out for our next release!

Share your thoughts on the Spine forum.