Meshspin.js is a simple and lightweight JavaScript library that lets you spin a 3D mesh object in your browser using SVG and JavaScript without dependencies.

German version

About meshspin.js

I developed meshspin.js about six months ago simply to add a little eye candy to our new company website. Since then many people, especially students in my software development classes asked me how it works and how they could use a similar effect in their own web projects.

After giving it a little bit of thought I decided to release the code to the public domain. Today I finally found the time to brush up the code and upload the repository to GitHub.

I tried to make meshspin.js as easy to use as possible. If you like meshspin.js donate a star on GitHub or share a link to this website.

Get started

To get started clone the meshspin.js repository from GitHub or link meshspin.min.js directly from kickstart.ch.

Basic HTML structure

<!doctype html> <body> <div id="wrapper"></div> <script src="http://kickstart.ch/js/meshspin.min.js"></script> <script> var mesh = new MeshSpin(); mesh.setup('wrapper'); mesh.run(); </script> </body>

This short code snippet will spin a tetrahedron mesh in your browser. By default the line color is set to the SVG currentColor which is accessible through CSS.

Object definition

To spin your own figure you have to call figure() with your own object definition. As a very basic example let's spin a cube.

To define your custom shape you need to specify its nodes and edges. A cube has 8 nodes and 12 edges. Nodes is an array of coordinates in the [x,y,z] space. To draw an edge you simply have to list the index numbers of the two connected nodes in the edges array.

Spinning cube example

var cube = { nodes: [ {x:1, y: 1, z: -1}, {x:1, y: -1, z: -1}, {x:-1, y: -1, z: -1}, {x:-1, y: 1, z: -1}, {x:1, y: 1, z: 1}, {x:1, y: -1, z: 1}, {x:-1, y: -1, z: 1}, {x:-1, y: 1, z: 1}, ], edges: [[0,1], [0,3], [0,4], [0,2], [1,3], [1,5], [1,2], [2,3], [2,6], [3,7], [4,5], [4,7], [5,6], [6,7]], }; var mesh = new MeshSpin(); mesh.figure(cube); mesh.setup('wrapper'); mesh.run();

Meshspin.js always spins objects around the origin [0, 0, 0]. Therefore make sure you distribute the nodes around [0, 0, 0].

SVG ViewBox and scale

The default SVG ViewBox is defined as [-100, -100, 200, 200]. This means X-Axis and Y-Axis start at negative 100 spanning 200 up to positive 100. Calling figure() will also scale your object by a default scale factor of 50. You can control these variables through .viewBox and .scaleFactor.

mesh.props.viewBox = [-10, -10, 20, 20]; mesh.props.scaleFactor = 5;

Enable 3D and set background color

In the next step we'll enable 3D to remove the lines behind the cube object and set a background color.

mesh.props.fake3D = true; mesh.props.background = true; mesh.props.fillColor = '#def';

The term fake3D indicates, that there is no full 3D calculation using Z-Buffering or a similar algorithm do detect visible faces. However fake3D should work properly for any convex object.

Control rotation and spin

You can use orientation to give your object an initial rotation. Use staticRotation to set the rotationSpeed per axis where 2 × PI is a full rotation.

mesh.props.orientation = {x: 0, y: Math.PI/4, z: 0 }; mesh.props.staticRotation = {x: -0.01, y: 0, z: 0.01};

Capture mouse movement

Meshspin.js comes with a built-in rotation callback that captures mouse movement.

mesh.getRotationOffset = mesh.rotateByMouse;

Custom rotation callback

Alternatively you can register your own rotation callback by overwriting getRotationOffset. GetRotationOffset is called for every frame.

mesh.getRotationOffset = function() { ... return { x:..., y:..., z:... } };


When creating a new shape you might find it useful to enable debugging.

var phi = (1 + Math.sqrt(5)) / 2; var dodecahedron = {} dodecahedron.nodes = [ {x:1, y: 1, z: 1}, {x:1, y: 1, z: -1}, {x:1, y: -1, z: 1}, {x:1, y: -1, z: -1}, {x:-1, y: 1, z: 1}, {x:-1, y: 1, z: -1}, {x:-1, y: -1, z: 1}, {x:-1, y: -1, z: -1}, {x:0, y: phi, z: 1/phi}, {x:0, y: phi, z: -1/phi}, {x:0, y: -phi, z: 1/phi}, {x:0, y: -phi, z: -1/phi}, {x:1/phi, y: 0, z: phi}, {x:1/phi, y: 0, z: -phi}, {x:-1/phi, y: 0, z: phi}, {x:-1/phi, y: 0, z: -phi}, {x:phi, y: 1/phi, z: 0}, {x:phi, y: -1/phi, z: 0}, {x:-phi, y: 1/phi, z: 0}, {x:-phi, y: -1/phi, z: 0}, ]; dodecahedron.edges = [[0,16], [0,8], [0,12], [1,9], [1,13], [1,16], [2,10], [2,12], [2,17], [3,11], [3,13], [3,17], [4,8], [4,14], [4,18], [5,9], [5,15], [5,18], [6,10], [6,14], [6,19], [7,11], [7,15], [7,19], [8,9], [10,11], [12,14], [13,15], [16,17], [18,19]]; var mesh = new MeshSpin(); mesh.props.fake3D = true; mesh.props.debug = true; mesh.getRotationOffset = function() { r = mesh.rotateByMouse(); return {x: r.x - 0.01, y: r.y - 0.005, z: 0.005}; }; mesh.figure(dodecahedron); mesh.setup('wrapper'); mesh.run();

Comments and bug reports

Please leave comments in the comment section below. Report bugs directly on the GitHub project page.