isolux.js

Isolux fields for the web.

The animated field behind this site, as a library you can use. Floating luminaires light a plane and the iso illuminance lines you choose are traced every frame, merging and splitting as the pools of light meet and part. One call and one JSON object, the way particles.js works.

StartingDrag a luminaire to move it. The cursor carries its own light.

Your configuration

Only what differs from the defaults. Paste it into your page or save it as JSON for isoluxJS.load.

How it works

Light first, then the lines.

Every frame isolux.js lights the plane, traces each level you asked for and draws it as one smooth line.

A real lighting model

Each luminaire is a point source over a horizontal plane: E = I cos θ / d². Pools fall off the way light does, so they meet, merge and part like the plans Lumadex draws.

Exact contours

Marching squares find each level on a grid. The segments are joined into whole lines, every point is moved onto the true contour of the field and each line is drawn as a spline.

Made to sit behind content

It pauses off screen and in background tabs, respects reduced motion, renders sharp on high density screens and follows your light and dark themes.

Getting started

A few lines to a lit page.

Add it

Download the one file, give the field a sized element and call isoluxJS with the element's id. Settings are optional; a preset name works too.

<div id="isolux"></div>
<script src="../isolux.js"></script>
<script>
  isoluxJS("isolux");            // the defaults
  isoluxJS("isolux", "road");    // or a preset
  isoluxJS("isolux", {
    preset: "soft",
    contours: { levels: [1, 2, 5, 10] }
  });
</script>

Load a configuration

Keep the settings in a JSON file, exactly as the playground downloads them.

isoluxJS.load("isolux", "isolux.json", function (field) {
  field.on("change", function (luminaires) {
    console.log(luminaires.length);
  });
});

Drive it

Every field is an object you can control.

var field = isoluxDom[0];
field.add(320, 180);     // a luminaire, faded in
field.remove(320, 180);  // the nearest one, faded out
field.set({ contours: { color: "ink" } });
field.pause(); field.play();
field.export();          // the configuration as JSON
field.destroy();

Place them yourself

Fixed positions with a road lantern distribution turn the field into a street lighting plan.

isoluxJS("isolux", {
  luminaires: {
    positions: [{ x: 0.2, y: 0.4 }, { x: 0.5, y: 0.4 }],
    distribution: { type: "road", spread: 2 }
  },
  move: { enable: false }
});
Download isolux.js

One file, nothing else to install: no dependencies, images or fonts. The MIT licence and a usage guide are in its header.

Options

Everything you can set.

Each option has a default, so a field works with no settings at all. The playground above writes these for you.

OptionDefaultWhat it does
luminaires.number.value7How many luminaires float in the field. With density on, scaled to the canvas area.
luminaires.positions[]Place luminaires yourself: x and y as fractions of the canvas (or pixels above 1), with optional intensity, mounting_height and rotate.
luminaires.mounting_height.value80Height above the plane in pixels. Low luminaires make tight bright pools; high ones spread wide and soft.
luminaires.distribution.type"organic"The shape of each pool: circle, oval, road, forward, batwing, square, clover, trefoil or organic (every pool its own breathing shape). A list mixes shapes; "random" picks one each; "custom" uses your own values.
luminaires.distribution.harmonicsper shapeLobes around a pool as [n, amount, phase]: 2 a batwing, 3 a trefoil, 4 a clover. With spread, throw, power (2 round, 4 square) and morph (lobes drift, in turns per minute) you can draw any distribution.
move.speed0.35Travel speed. With move.enable false every luminaire holds still.
move.drift.amplitude36A slow orbit around each travelling position, in pixels.
move.out_mode"bounce""bounce" keeps luminaires near the canvas; "out" lets them leave and return on the far side.
field.model"cosine""cosine" is a point source over a horizontal plane (I cos θ / d²); "gaussian" is a soft pool without the long tail.
field.scale20Illuminance in lux directly below a luminaire of intensity 1. Levels are read against it.
contours.levels[1, 2, 3, 5, 10, 15]The isolux lines to draw, in lux. As pools meet the lines merge; as they part, the lines split.
contours.color"spectrum""spectrum" (the Lumadex fan from low to high), "ink" (follows the theme), one colour or a list per level.
contours.fillenable, opacity 0.14A soft glow of the field itself, coloured by band.
contours.labelsenable, "{value} lx"A label on the longest runs of each level, aligned with its line, in a clean gap. Labels slide with their line instead of jumping.
interactivity.detect_on"canvas""window" listens across the page so a field behind your content still responds; ignore lists the elements it should not react over.
interactivity.events.onhover.mode"light""light" (the cursor carries its own luminaire), "repulse", "attract" or "bubble".
interactivity.events.onclick.mode"add""add", "remove" or "pulse". Luminaires fade in and out.
interactivity.events.ondrag.enabletruePick up a luminaire and move it. It drifts on from where you drop it.
theme.mode"auto"Follows the page's theme attribute (set in theme.attribute), then the system setting. Each theme has its own ink, background and opacity.
performance60 fps, retinafps_limit, retina_detect, pause_offscreen and reduced_motion (respects the visitor's setting).
In Lumadex

The same field while Lumadex loads.

Lumadex Desktop shows an isolux field while it starts and while a project opens. It reads the same JSON as isolux.js and draws it natively on its own thread, so the light keeps moving while the project loads.

Lumadex Lumadex Opening Riverside car park
Driven by lumadex-loading.json, the file Lumadex Desktop ships.

See the real thing on one of your own sites.

We would welcome the chance to take your team through Lumadex against the Standards you design to. Draw the area and see the first calculation before the survey arrives.

Contact

Talk to the Lumadex team.

Ask for a demonstration, a trial or a quote or tell us about a project.

Fields marked * are required. Do not include passwords, licence keys or confidential project data. Sending opens your email program with the enquiry ready to send.

Enter your name.
Enter a valid email address.
Enter a subject.
20 to 4,000 characters.Write at least 20 characters.

Your email program has opened with the enquiry. If it did not, email us at admin@galaxypixelstudios.au.