Exporting 2d bone animation from Blender to vanilla JavaScript



Blender is an awesome free animation tool. It focuses on 3d animation, but it's also great for 2d. Let's import animation created in Blender to JavaScript - the stickman above is being drawn realtime on an HTML5 Canvas by JS. As you can see, I suck at character animation, but Blender offers great functionality like Inverse Kinematics, keyframes, interpolation, pose library etc.:



Blender comes with a built-in Python interpreter. Here's a short snippet that exports the coordinates of the bones to a "coords.js" file:

import bpy
import os
with open('c:/javascript/coords.js', 'w') as file:
    file.write('let coords=[')
    bones = ['spine','head','arm.l','forearm.l','thigh.l','shin.l','arm.r','forearm.r','thigh.r','shin.r']
    for f in range(226):
        bpy.context.scene.frame_set(f)
        p = bpy.data.objects['Armature'].location + bpy.data.objects['Armature'].pose.bones['spine'].head
        file.write(str(round(p.x)) + ',' + str(round(p.y)) + ',')
        for n in range(10):
            p = bpy.data.objects['Armature'].location + bpy.data.objects['Armature'].pose.bones[bones[n]].tail
            file.write(str(round(p.x)) + ',' + str(round(p.y)) + ',')
    file.write('];')


Click here for simple step-by-step instructions if you're new to Blender Python.

Click here to download the .blend animation file for Blender (this is optional)

It actually generates a one line JS program that just creates the "coords" array. We have a little animated armature (skeleton) consisting of several bones (spine, head, arms, forearms etc). The script first opens the output file, then goes through every frame and writes the x and y coordinates of every bone to the file, separated by commas. The first point is the head of the spine (Blender calls the starting point of a bone a "spine", but in this situation it is ironically placed on the character's butt) and following points are located at the bones' "tails". We're doing a 2d animation here to keep things simple, but the same concept would work for three dimensions.
Now the JS part:

<html>
<body>
<canvas id="myCanvaswidth="600height="600"></canvas>
<script src='coords.jstype='text/javascript'></script>
<script>
let frame = 0;
let canvas = document.getElementById('myCanvas');
let context = canvas.getContext('2d');
 
function line(p1, p2) {
  context.beginPath();
  context.moveTo(p1.x, p1.y);
  context.lineTo(p2.x, p2.y);
  context.stroke();
}
 
function draw() {
  context.clearRect(00600600);
  let points = [];
  for (let n = 0n < 11n++) {
    let point = {
      xcoords[frame * 2 * 11 + n * 2],
      y400 - coords[frame * 2 * 11 + n * 2 + 1]
    };
    points.push(point);
  }
  context.beginPath();
  context.arc(points[2].xpoints[2].y3002 * Math.PI);
  context.stroke();
  line(points[0], points[1]);
  line(points[1], points[3]);
  line(points[3], points[4]);
  line(points[0], points[5]);
  line(points[5], points[6]);
  line(points[1], points[7]);
  line(points[7], points[8]);
  line(points[0], points[9]);
  line(points[9], points[10]);
  frame++;
  if (frame == 226)
    frame = 0;
  window.requestAnimationFrame(draw);
}
 
context.lineWidth = 10;
context.lineCap = 'round';
draw();
 
</script>
</body>
</html>


[4] imports the coordinates file generated by Python
[10-15] function that draws a line from Point 1 to Point 2
[17-43] the main animation loop:
[18] clear the previous frame
[20-26] create an array of 11 points for the given frame. Each point is an object with x and y coordinates.
[27-38] draw a circle for the head and lines for spine and limbs. To make it look better, you can draw .png or .svg images instead of these simple shapes.

This is a relatively simple example to demonstrate the idea. You could make it more interesting (and complicated) by having multiple characters and their actions (jump, fall etc) and locations driven by the user.



Check out these programming tutorials:

Python in Blender 3d:

Domino effect (10 lines)


Wrecking ball effect (14 lines)

3d fractal in Blender Python

JavaScript:

Animated particle constellations (42 lines)

Optical illusion (18 lines)

Spinning squares - visual effect (25 lines)

Oldschool fire effect (20 lines)

Fireworks (60 lines)

Animated fractal (32 lines)

Minesweeper game (80 lines)

Physics engine for beginners

Physics engine - interactive sandbox

Physics engine - silly contraption

Starfield (21 lines)

Yin Yang with a twist (4 circles and 20 lines)

Tile map editor (70 lines)

Sine scroller (30 lines)

Turtle graphics

Interactive animated sprites

Image transition effect (16 lines)

Wholla lotta quadratic curves (50 lines)

Your first program in JavaScript: you need 5 minutes and a notepad


Fractals in Excel