OffscreenCanvas Playground - Interactive Lab | IconVault

Race OffscreenCanvas in a real Web Worker against main-thread rendering with live FPS. Free, runs fully in your browser.

All tools

OffscreenCanvas Playground

Main-thread vs worker rendering FPS comparison

5 of 5 free uses left
Support:Not supported in this browser

Main thread

classic 2D context, blocks the UI thread

-- FPS

Web Worker

OffscreenCanvas painted off the main thread

-- FPS

Worker source code (the real thing)

let canvas, ctx, parts = [], w = 0, h = 0, last = 0, frames = 0;

onmessage = (e) => {
  const d = e.data;
  if (d.type === "init") {
    canvas = d.canvas; w = d.w; h = d.h;
    canvas.width = w; canvas.height = h;
    ctx = canvas.getContext("2d");
    spawn(d.count);
    last = performance.now();
    requestAnimationFrame(tick);
  }
  if (d.type === "count") spawn(d.count);
  if (d.type === "resize") { w = d.w; h = d.h; canvas.width = w; canvas.height = h; }
};

function spawn(n) {
  parts = [];
  for (let i = 0; i < n; i++) {
    parts.push({
      x: Math.random() * w, y: Math.random() * h,
      vx: (Math.random() - 0.5) * 4, vy: (Math.random() - 0.5) * 4,
      r: 1 + Math.random() * 2.5,
      hue: 150 + Math.random() * 40,
    });
  }
}

function tick(now) {
  ctx.fillStyle = "#0b1220";
  ctx.fillRect(0, 0, w, h);
  for (const p of parts) {
    p.x += p.vx; p.y += p.vy;
    if (p.x < 0 || p.x > w) p.vx *= -1;
    if (p.y < 0 || p.y > h) p.vy *= -1;
    ctx.fillStyle = "hsl(" + p.hue + " 80% 60%)";
    ctx.beginPath();
    ctx.arc(p.x, p.y, p.r, 0, 6.2832);
    ctx.fill();
  }
  frames++;
  const t = performance.now();
  if (t - last >= 500) {
    postMessage({ type: "fps", fps: Math.round((frames * 1000) / (t - last)) });
    frames = 0; last = t;
  }
  requestAnimationFrame(tick);
}

5 of 5 free copies left.

About this tool

IconVault's OffscreenCanvas Playground races an OffscreenCanvas rendered in a real Web Worker against identical main-thread canvas rendering, with live FPS meters for both. Drag the particle count up and watch where each renderer starts to drop frames. It is free to use and runs fully in your browser with nothing uploaded.

How to use: press Start race, then raise the particle slider to stress both renderers. Perfect for developers building games, data visualizations and creative tools who want to see exactly when moving paint work off the main thread pays off.

Frequently asked questions

Popular searches

offscreen canvasoffscreencanvas examplecanvas web workeroffscreen canvas worker examplecanvas fps testweb worker canvas renderingoffscreencanvas tutorialmain thread vs worker canvascanvas performance testoffscreencanvas browser supporttransfercontroltooffscreen examplecanvas render performanceoffscreencanvas reactweb worker renderingcanvas fps counteroffscreencanvas particlescanvas animation workeroffscreen canvas mdnlearn offscreencanvascanvas jank fixmove canvas to workeroffscreencanvas typescriptwebgl offscreen canvascanvas 2d workeroffscreencanvas commitrequestanimationframe workercanvas performance benchmarkjavascript canvas fpsworker canvas demooffscreencanvas safarioffscreencanvas firefoxcanvas off main threadfrontend performance canvasgame loop web workerparticle system canvascanvas rendering optimizationoffscreencanvas vs canvasweb worker graphicscanvas thread blockingsmooth canvas animationhigh performance canvascanvas benchmark tooloffscreencanvas example codelearn web workerscanvas worker tutorialoffscreen rendering web60fps canvas tipscanvas fps drop fixweb worker canvas transferoffscreencanvas playgroundcanvas performance lab

More tools

Coming soon

CLI

Coming soon

Figma plugin

Coming soon

VS Code extension

Coming soon

Chrome extension

Coming soon

AI icon generator

Coming soon

Team workspaces

Coming soon

View all 10+ tools →