‹ Phoria demos

Getting started

Two short walk-throughs: a first 3D scene, then a live dashboard of 3D charts. Every step is a complete program, running beside its code - copy any step as one HTML file, or open it in CodePen to change it. About fifteen minutes, start to finish.

Setting up

Nothing to install: one HTML file will do. An import map tells the browser where 'phoria2' comes from - here a CDN, pinned to version - and your code imports from it as it would from npm. This is the first step below, as the whole file:

Save it as index.html and open it in a browser. Every step's Copy as one page button gives you its file like this, ready to run.

Part 1: a first scene

1. A box on the page

A View draws into a canvas - give it the element or a CSS selector. What it draws is its scene. A Mesh is a shape (geometry) with a look (material), and a material is a plain object of options.

There's no camera or light in the code, and still a lit box in view: with no camera given, the View looks at the scene from the front, to the right and a little above, and fits it in; with no lights, it lights the scene itself and says so in the console. The View also draws only when something changes - this still picture costs nothing after its first frame.

2. Light and motion

orbit: true lets you turn the view: drag to orbit, right-drag to pan, scroll to zoom. A DirectionalLight shines like the sun, all one way - direction is the way its light travels, here down and away. scene.add() hands back what it added, so you can keep hold of it.

view.start() calls your function every frame, with the seconds since the last (dt). Multiplying by it keeps the speed the same on any screen - here 0.6 radians a second.

3. Materials, a floor and shadows

Positions are in metres, with Y up. roughness runs from a mirror (0) to matte (1), and metalness: 1 makes a metal, which reflects its surroundings in its own colour - environment: 'studio' gives it a built-in photo studio to reflect (an .hdr file works too). For shadows, the light casts them, the shapes cast them and the floor catches them.

4. Labels

A Label is an HTML element pinned to a point in 3D, so it's sharp at any size, selectable, and styled with CSS - this step brings a little of each, in its HTML. Added to the cube rather than the scene, a label goes wherever the cube goes; its position is measured from the cube's middle.

5. Hover and click

highlight tints whatever is under the pointer, and tooltip gets a hit - what's under the pointer - and returns what to show. view.on('click') gets a hit too, or null for empty space. The floor is set pickable: false, so the pointer passes through it.

Part 2: a chart dashboard

1. A bar chart from rows

chart(), from phoria2/charts, turns rows of data into a chart: axes, ticks, grid, legend and tooltips included. Name the fields to use - x and z for the rows of bars, y for their height, color for their colour - and tooltip: true shows every field on hover. view.frame() moves the camera to fit the chart.

A chart is an ordinary node in the scene: orbit round it, hover the bars, and click the legend's swatches to hide and show a region.

2. Live data

chart.update(rows) moves the bars to new figures. A field can be given as an object, with a title and a format for the axis and tooltips - here the sales are thousands of pounds.

The View draws while the bars move, then stops until the next update - a dashboard that's left open costs almost nothing between refreshes.

3. A dashboard of views

Each tile is its own View on its own canvas, laid out with ordinary CSS grid. A page can hold any number of them: browsers allow only around 16 WebGL contexts, so phoria2 gives the first four their own and draws the rest through one shared context, each still its own canvas. framing: 'both' keeps the whole chart in its tile, whatever shape the tile becomes.

The same rows make all three charts - only the mark changes: bars, lines, and areas stacked to a total. A small tile() function keeps the repetition out.

4. Linked views

A click on a bar gives a hit whose datum is the row behind that bar. chart.filter() shows only the rows a function keeps, so clicking a bar narrows the other two tiles to its region; clicking empty space passes null, and they show every region again. The filter stays as the data updates.

Where next

Copyright © Kevin Roast 2013-2026 · GitHub · npm