Isometric Rubik's

An interactive visualisation of a grid of Rubik's cubes rendered in isometric projection. Each cube performs random layer rotations with satisfying "finger flick" easing, creating a hypnotic pattern. The synchronised mode aligns all cube movements for a particularly mesmerising effect.

Interactive Demo

Interact with the full experience below. Open the settings panel to adjust animation speed, enable sync mode, or try different colour schemes.

Features

  • Isometric Projection — Classic 30°/45° camera angle for that clean, geometric aesthetic
  • Sync Mode — All cubes rotate together in perfect harmony
  • 7 Colour Schemes — Classic, Neon, Ocean, Sunset, Forest, Pastel, and Monochrome
  • Accelerating Solve — Watch the cubes solve with increasing speed
  • Hover Mode — Cubes rotate when you mouse over them

Implementation

The visualisation uses Three.js with an orthographic camera set to isometric angles. Each Rubik's cube is a group of 27 cubies with shared geometry and materials for optimal performance.

// Orthographic camera for isometric view
const camera = new THREE.OrthographicCamera(
  -frustumSize * aspect / 2,
  frustumSize * aspect / 2,
  frustumSize / 2,
  -frustumSize / 2,
  0.1, 1000
);

// Classic isometric angles: 30° X, -45° Y
camera.rotation.order = 'YXZ';
camera.rotation.y = -Math.PI / 4;  // -45°
camera.rotation.x = Math.atan(1 / Math.sqrt(2));  // ~35.26°

Layer rotations use a pivot group technique — cubies in the rotating layer are temporarily parented to a pivot, rotated, then reparented back with snapped positions. The "finger flick" easing mimics the feel of a real cube turn.

// Custom easing for natural rotation feel
function fingerFlickEase(t) {
  // Quick start, smooth deceleration
  const c1 = 1.70158;
  const c3 = c1 + 1;
  return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
}

The solve animation uses an ease-out cubic curve to accelerate quickly at the start, creating a satisfying rush as the cubes return to their solved state.

getSolveSpeedMultiplier() {
  const progress = this.solveCurrentMoveIndex / this.solveTotalMoves;
  const minMultiplier = 1;
  const maxMultiplier = 25;

  // Ease-out cubic: fast at start, levels off
  const eased = 1 - Math.pow(1 - progress, 3);

  return minMultiplier + (maxMultiplier - minMultiplier) * eased;
}

Keyboard Shortcuts

KeyAction
SpaceToggle play/pause
EnterSolve all cubes
HToggle UI visibility
MToggle hover mode
1-7Switch colour schemes

Inspiration

This project was inspired by a Reddit post on r/creativecoding featuring procedurally generated Rubik's cube patterns. The original concept sparked the idea to create a fully interactive, configurable version with real-time layer rotations and multiple visual themes.