Showcase · Three.js · WebGPU · TSL

Isometric data cards: 3D charts that turn into real charts

Three stat cards drawn like technical drawings. Hover a card and point at a bar, a slice or an hour, then click to fold the drawing flat into a readable chart. Everything is rendered live in your browser.

  • Productive days

    W42
    Peak Wednesday · 7.9 h

    Deep-work hours per weekday, from calendar and editor activity. The ball marks the day you point at.

  • Spending patterns

    OCT
    Up 18% Dining out · 24%

    Share of monthly spending by category. Dining out grew 18% against September.

  • Busiest hours

    24H
    Peak 14–18h · 38% of sessions

    Sessions per hour of the day. Tick length is activity; the light rests on the busiest stretch.

Hover the cards · click one to flatten it

Showcase · Three.js · WebGPU · TSL

What you're looking at

Isometric Data Cards is a set of three interactive stat cards for a dashboard or a landing page. Each card holds an isometric line drawing of its data: a 3D bar chart, a 3D pie chart and a lighthouse on a 24-hour dial. Lines that would be hidden behind a solid are dashed, like in an engineering drawing.

The motion carries meaning instead of decoration. A marker ball hops to the bar you point at, a slice slides out to be read, the lighthouse lights the hour under your cursor. Click a card and the drawing folds flat into an ordinary chart with axes and values, so the playful view and the precise view are the same object.

chart types: bar, pie and radial
3chart types: bar, pie and radial
canvas for all cards, drawn over the HTML
1canvas for all cards, drawn over the HTML
views per card: isometric and flat
2views per card: isometric and flat
chart images: every label is HTML text
0chart images: every label is HTML text

The three cards

A 3D bar chart, a 3D pie chart and a radial chart

Each card answers one question, and each animation shows the answer instead of decorating it.

Productive days: a 3D bar chart with a marker ball

Seven bars for seven weekdays. The bars never move, because they are the data. An orange ball rests on the peak; point at another day and it hops over in an arc, lands with a squash and a small bounce, and that bar's top face lights up.

Technique: The ball is simulated: gravity, a take-off speed that clears the bars in between, restitution on landing and a damped squash spring. It throws a soft orange light on the bar top beneath it.

Spending patterns: a 3D pie chart

Five slices, one per category. The slice under the pointer turns orange and slides a little out of the pie, its light falling on a dotted ground plane. At rest the card highlights the category that changed most.

Technique: Slices are extruded sectors. Their curved walls get silhouette lines computed per frame, so the outline stays correct from any angle and during the flattening.

Busiest hours: a radial chart with a lighthouse

A 24-hour dial where tick length is activity. The lighthouse throws a cone of light down onto the dial: at rest over the busiest stretch, on hover onto the hour you point at, with its share of the peak.

Technique: The light is a cone stretched each frame from the lamp to a spot on the dial, with a light pool where it lands. The hour comes from where the pointer ray meets the dial plane.

How it's built

How to draw isometric charts with hidden lines in Three.js

The drawings use the Three.js WebGPURenderer and TSL, the Three.js Shading Language. One orthographic camera in CSS pixels covers the page, so every chart can sit exactly on its HTML card and still leave it.

  1. 1. Solid lines in front, dashed lines behind

    Every edge is drawn twice. The second pass only draws where the depth test says the edge is hidden, and draws it dashed. Depth-only solids, shrunk by half a pixel, do the hiding.

    kit.ts
    // Every solid is drawn as its edges, twice.
    // In front: solid lines. Behind something: dashed.
    const front = new Line2NodeMaterial({ linewidth: 1.25 })
    const behind = new Line2NodeMaterial({
      linewidth: 1, dashed: true, dashSize: 3, gapSize: 3.5,
      depthFunc: THREE.GreaterDepth, // only where hidden
    })
    // Depth-only solids, a hair smaller, hide the edges behind them.
    const solid = new MeshBasicNodeMaterial({ colorWrite: false })
  2. 2. Outlines for curved surfaces

    A cylinder has no edges along its wall, so a pie slice or the lighthouse would lose its outline. Each frame, two silhouette lines are placed where the wall turns away from the viewer.

    kit.ts
    // Curved walls have no edges: find where the wall turns away.
    // n(a) · view = 0  ->  A cos a + B sin a = C
    const d = viewDir.transformDirection(inverseWorldMatrix)
    const k = (r0 - r1) / (y1 - y0) // taper of the cone
    const phi = Math.atan2(-d.z, d.x)
    const delta = Math.acos(-k * d.y / Math.hypot(d.x, d.z))
    const silhouettes = [phi + delta, phi - delta]
  3. 3. A bouncing ball with real physics

    The marker ball is not tweened. It jumps with a speed that clears every bar on the way, can be steered mid-air when you change your mind, and loses energy with every bounce.

    charts.ts
    // Hop to the next bar: an arc that clears everything between.
    const jump = (lift: number) => {
      ball.vy = Math.sqrt(2 * G * (clearance() + lift - ball.y))
      const t = (ball.vy + Math.sqrt(ball.vy ** 2 + 2 * G * (ball.y - landY))) / G
      ball.vx = (targetX - ball.x) / t
    }
    // On touch-down: squash by impact speed, bounce with less energy.
    if (ball.y <= landY) ball.vy = impact > 120 ? impact * 0.42 : 0
  4. 4. Precise hover by picking the data, not the mesh

    Raycasting the bars or slices fails as soon as they move. The pointer ray is intersected with a plane in the chart's own space instead, and the position on that plane names the day, the category or the hour.

    charts.ts
    // Pick by column, not by mesh: intersect the pointer ray
    // with the vertical plane through the bars.
    inverse.copy(chart.matrixWorld).invert()
    ray.copy(raycaster.ray).applyMatrix4(inverse)
    if (ray.intersectPlane(barPlane, hit)) {
      active = Math.round((hit.x - firstBarX) / STEP)
    }
  5. 5. From isometric drawing to flat chart

    On click the card grows into the middle of the screen while the drawing rotates to a straight view and its depth is pressed flat. Axis labels and values fade in as HTML at the end of the motion.

    IsometricCards.ts
    // Isometric -> flat: rotate to a straight view and
    // press the depth axis flat, in one eased motion.
    q.slerpQuaternions(Q_ISO, chart.qFlat, eased)
    chart.root.quaternion.copy(q)
    chart.root.scale[chart.collapse] = scale * lerp(1, 0.02, eased)

Interaction

Hover, point and click: interaction with a purpose

Every reaction answers a question about the data, so playing with the cards is also reading them.

Invert on hover

The hovered card flips from dark to cream and its line drawing switches ink, in step with the 3D.

Point at the data

The bar, slice or hour under your cursor becomes the active one, and its value appears beside it and in the card footer.

Click to flatten

The drawing folds into a 2D chart with axes and values. Click again, press Escape or click outside to fold it back.

Keyboard and screen readers

Cards are focusable and open with Enter or Space. Each card carries a text description of its chart.

Performance

Light enough to sit on a landing page

Three charts should not cost a laptop fan. These choices keep the cards cheap.

  • One canvas, three cards

    All drawings share one renderer and one camera in CSS pixels, placed on the HTML cards every frame.

  • Render only when visible

    The engine loads when the section comes near and stops drawing once it is off screen and every card is back in place.

  • HTML for every word

    Titles, values, axis labels and footers are HTML, readable by search engines and screen readers, and sharp at any zoom.

  • WebGPU first, WebGL 2 fallback

    The WebGPURenderer uses WebGPU where available and WebGL 2 elsewhere. The same TSL code runs on both.

For your product

Interactive data visualization for dashboards and landing pages

The same building blocks work with your own numbers:

SaaS dashboards

Stat cards that explain a metric at a glance and open into a precise chart.

Analytics and reporting

Weekly reports and year-in-review pages people actually explore.

Landing page heroes

Show what your product measures with live, playful charts instead of screenshots.

Fintech and budgeting apps

Spending breakdowns and savings goals with a slice or a bar that responds to touch.

Fitness and habit tracking

Streaks, busiest days and best hours visualised as small objects.

Data storytelling

Isometric scenes for editorial pages, annual reports and pitch decks on the web.

I build it to your brief: your data, your colours, the chart types you need, in plain Three.js or inside React and Next.js. You get clean, documented code that works on phones too.

TypeScript, React & Next.js development

Questions about isometric 3D charts

What is an isometric chart?

An isometric chart draws data as 3D objects seen from a fixed angle without perspective, so parallel lines stay parallel and sizes stay comparable. It looks like a technical drawing and keeps values easier to compare than a perspective 3D chart.

Are 3D bar and pie charts bad for reading data?

Perspective 3D charts distort values. These cards use an isometric view for the overview and fold into an ordinary flat chart with exact values on click, so nothing is hidden behind the effect.

Can I feed it my own data?

Yes. Each chart takes plain arrays of numbers and labels. Live data from an API or a database works the same way.

Does it work in React or Next.js?

Yes. The engine is a framework-free TypeScript class that a small client component mounts and disposes. This page is a Next.js page.

Does a WebGL section hurt SEO or page speed?

Not when built like this. All text is server-rendered HTML. The engine loads when the section comes near and stops drawing when it is off screen.

What does a set of cards like this cost?

I work at 75 USD per hour. The total depends on the number of charts, the interactions and the integration into your product. We agree on scope and an estimate before I start.

Freelance · $75 USD / hour · Worldwide

Let's make your numbers worth exploring.

Tell me what you want to show, where it will live and your timeline. I reply with questions or a first estimate. Writing in German is fine too.

Design inspiration: the interactive isometric data cards by Zsolt Kacso. This version was rebuilt from scratch with Three.js, WebGPU and TSL. Original post on X