Iron Filings & Magnetic Fields Visualised With JavaScript

Magnetic fields in canvas and Pixi.js

Visualising a bar magnet's field with sprite "iron filings" driven by a physics equation in JavaScript.

Published 1 Sep 2015 at 10:00 Updated 24 Jul 2026 at 10:00

We all remember playing with magnets as kids. One popular experiment to show how magnets work uses iron filings suspended on a sheet of paper held above a bar magnet.

This gives a good visualisation of the size and placement of the magnetic fields surrounding the magnet.

This demo a simple little demo to show how mathematical functions can be applied to achieve relatively complex effects rendered with javascript and HTML <canvas> elements

Demo: “iron filings” — image sprites rendered with Pixi.js — aligning to a computed magnetic field around a bar magnet. Originally a CodePen (“Magnets. How do they work? (WIP)”, solarisedesign/XmdEBa).

2026 update The CodePen embed is being re-hosted here; the interactive version will return.

Here you can see an initial attempt to render the effects of a magnetic field by introducing “iron filings” – which are actually just image sprites rendered with the Pixi.js library and animated using a mathematical function.

There are still a lot of features that I hope to eventually implement, to create more realistic behaviour (listed below).

For reference, here’s an image of the classic “bar magnet with iron filings” experiment which shows the iron filings aligning along the lines of the magnetic fields:

Reference photograph: the classic bar-magnet experiment, iron filings tracing the field lines between the poles. (Original image asset was hosted on a since-retired staging server.)

For those who may be interested, I found reference to the appropriate equation in a physics textbook and when written in Javascript, it looks a little something like:

var B = (Math.pow(10, -7) * Math.sqrt(1 + 3 * Math.pow(Math.cos(angle), 2))) / Math.pow(distance/1000, 3);

Now, I’m certainly no mathematician. In fact, I’d class myself more as an engineer (i.e. definitely not a mathematician) but it seems like the above formula does the trick, and generates something that looks like it probably works as a magnetic field simulation. To the engineer part of my brain, that’s good enough.

From my understanding, the formula above will estimate the magnetic field strength at a given point, but I was trying to simulate a bar magnet (i.e. made up of a large number of individual magnetic points). So, to achieve that, I calculated the field strength at multiple points on the “magnet”, and then from that derived an average. Again, this may not be strictly the right approach, but it seems to work.

Further Work

There’s plenty more to do here though:

  • Verify that the above formula is indeed producing accurate figures. The formula should be generating a magnetic field effect that is accurate given a specific strength of magnet.
  • Enable the “iron filings” to move towards the magnetic poles. This will likely be tricky, as in the image they can be seen to be clumping together (the filings themselves becoming magnetised and forming chains, running along the magnetic field lines) – Also, this may be quite computationally expensive.
  • The internal magnetic field doesn’t seem to be represented fully. In the image you can see the magnetic lines extending between north and south. This may be due to the filings in the image moving towards the magnetic poles though.
  • There appears to be a very distinct vertical “cutoff” occuring at the central point of the magnetic field on the x-axis. I suspect this is due to some error in the implementation of the formula, or within the rendering code.

Heads up This predates Pixi v8. The Pixi API has changed shape: Application now initialises asynchronously, so the old synchronous new PIXI.Application({...}) constructor pattern won’t give you a ready renderer.

const app = new Application();
await app.init({ resizeTo: window, antialias: true });
document.body.appendChild(app.canvas);

The “computationally expensive” per-filing field maths is also a natural fit for a fragment shader now — compute the field direction per pixel on the GPU (Pixi v8’s Filter / mesh shaders, WebGL or WebGPU) and the whole-screen field becomes cheap, sidestepping the per-sprite averaging entirely.

All articles

Let's talk.

I help content-rich organisations understand their data and pull it back into one place. Tell me what specific problems you're having and I'll be happy to talk solutions with you.