Web APIs Cheatsheet

Canvas

Use this Web APIs reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Getting the Context

const canvas = document.getElementById('c');
const ctx = canvas.getContext('2d');

// HiDPI / Retina
const dpr = window.devicePixelRatio || 1;
canvas.width  = canvas.offsetWidth  * dpr;
canvas.height = canvas.offsetHeight * dpr;
ctx.scale(dpr, dpr);

// WebGL
const gl  = canvas.getContext('webgl2');       // WebGL 2
const gl1 = canvas.getContext('webgl');        // WebGL 1 fallback
// Context attributes
canvas.getContext('2d', { alpha: false, desynchronized: true, colorSpace: 'display-p3' });
canvas.getContext('webgl2', { antialias: true, depth: true, powerPreference: 'high-performance' });

Canvas Properties

PropertyDescription
canvas.widthBuffer width in pixels (CSS pixels × DPR)
canvas.heightBuffer height in pixels
ctx.canvasBack-reference to the canvas element

Drawing State (save / restore)

ctx.save();     // push state: transforms, clip, all style properties
ctx.restore();  // pop state

// Stackable
ctx.save();
  ctx.translate(50, 50);
  ctx.save();
    ctx.rotate(Math.PI / 4);
    ctx.fillRect(-20, -20, 40, 40);
  ctx.restore();
ctx.restore();

Transforms

ctx.translate(x, y);
ctx.rotate(angleRad);                      // clockwise
ctx.scale(sx, sy);

// Set transform matrix directly (replaces current)
ctx.setTransform(a, b, c, d, e, f);       // [a c e / b d f / 0 0 1]
ctx.setTransform(new DOMMatrix());

// Multiply into current transform
ctx.transform(a, b, c, d, e, f);

// Read current transform
const m = ctx.getTransform();              // DOMMatrix
ctx.resetTransform();                      // identity

Rectangles

ctx.fillRect(x, y, w, h);
ctx.strokeRect(x, y, w, h);
ctx.clearRect(x, y, w, h);      // erase to transparent

Paths

ctx.beginPath();                         // clear current path
ctx.moveTo(x, y);
ctx.lineTo(x, y);
ctx.arc(cx, cy, radius, startAngle, endAngle, anticlockwise);
ctx.arcTo(x1, y1, x2, y2, radius);      // rounded corner
ctx.ellipse(cx, cy, rx, ry, rotation, startAngle, endAngle, anticlockwise);
ctx.rect(x, y, w, h);
ctx.roundRect(x, y, w, h, radii);       // CSS-style border-radius (modern)
ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);   // cubic Bézier
ctx.quadraticCurveTo(cpx, cpy, x, y);               // quadratic Bézier
ctx.closePath();                         // line back to start

ctx.fill('nonzero');                     // 'nonzero' (default) | 'evenodd'
ctx.stroke();
ctx.clip('nonzero');                     // clip to path
ctx.isPointInPath(x, y);                // boolean
ctx.isPointInStroke(x, y);             // boolean

Path2D

const p = new Path2D();
p.arc(50, 50, 30, 0, Math.PI * 2);
p.addPath(otherPath, new DOMMatrix().translate(100, 0));

const svgPath = new Path2D('M 10 10 L 90 90');

ctx.fill(p);
ctx.stroke(p);
ctx.clip(p);
ctx.isPointInPath(p, x, y);

Fill and Stroke Styles

ctx.fillStyle = 'red';
ctx.fillStyle = '#ff0000';
ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
ctx.fillStyle = ctx.createLinearGradient(x0, y0, x1, y1);
ctx.fillStyle = ctx.createRadialGradient(x0, y0, r0, x1, y1, r1);
ctx.fillStyle = ctx.createConicGradient(startAngle, x, y);
ctx.fillStyle = ctx.createPattern(image, 'repeat');  // 'repeat' | 'repeat-x' | 'repeat-y' | 'no-repeat'

ctx.strokeStyle = /* same options as fillStyle */;

// Gradients
const g = ctx.createLinearGradient(0, 0, 200, 0);
g.addColorStop(0, 'red');
g.addColorStop(0.5, 'yellow');
g.addColorStop(1, 'blue');
ctx.fillStyle = g;

Line Style Properties

PropertyValuesDefault
ctx.lineWidthnumber1
ctx.lineCap'butt' 'round' 'square''butt'
ctx.lineJoin'miter' 'round' 'bevel''miter'
ctx.miterLimitnumber10
ctx.setLineDash([5, 3])
ctx.getLineDash()number[][]
ctx.lineDashOffsetnumber0

Shadows

ctx.shadowOffsetX = 4;
ctx.shadowOffsetY = 4;
ctx.shadowBlur = 8;
ctx.shadowColor = 'rgba(0,0,0,0.5)';
// Disable: set blur and offsets back to 0
ctx.shadowColor = 'transparent';

Text

ctx.font = 'bold 16px sans-serif';      // CSS font shorthand
ctx.textAlign = 'left';                 // 'left' | 'right' | 'center' | 'start' | 'end'
ctx.textBaseline = 'alphabetic';        // 'top' | 'hanging' | 'middle' | 'alphabetic' | 'ideographic' | 'bottom'
ctx.direction = 'ltr';                  // 'ltr' | 'rtl' | 'inherit'
ctx.letterSpacing = '2px';             // CSS string (modern)
ctx.wordSpacing = '4px';               // CSS string (modern)

ctx.fillText('Hello', x, y, maxWidth?);
ctx.strokeText('Hello', x, y, maxWidth?);

const m = ctx.measureText('Hello');
m.width;
m.actualBoundingBoxAscent;
m.actualBoundingBoxDescent;
m.fontBoundingBoxAscent;
m.fontBoundingBoxDescent;

Images and Pixels

// drawImage(source, dx, dy)
ctx.drawImage(img, 0, 0);
// drawImage(source, dx, dy, dw, dh)
ctx.drawImage(img, 0, 0, 200, 200);
// drawImage(source, sx, sy, sw, sh, dx, dy, dw, dh) — crop + scale
ctx.drawImage(video, sx, sy, sw, sh, dx, dy, dw, dh);

// Source types: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement,
//               ImageBitmap, OffscreenCanvas, VideoFrame

// Pixel data
const imageData = ctx.getImageData(x, y, w, h);
const { data, width, height } = imageData;
// data is Uint8ClampedArray: [R, G, B, A, R, G, B, A, ...]
for (let i = 0; i < data.length; i += 4) {
  data[i]     // R
  data[i + 1] // G
  data[i + 2] // B
  data[i + 3] // A (0–255)
}

ctx.putImageData(imageData, dx, dy);
ctx.putImageData(imageData, dx, dy, sx, sy, sw, sh); // dirty rect

// Create blank ImageData
const blank = ctx.createImageData(w, h);
const copy  = ctx.createImageData(existingImageData);

Compositing

ctx.globalAlpha = 0.5;           // 0–1

ctx.globalCompositeOperation = 'source-over'; // default
// Values: 'source-over' | 'source-in' | 'source-out' | 'source-atop'
//         'destination-over' | 'destination-in' | 'destination-out' | 'destination-atop'
//         'lighter' | 'copy' | 'xor'
//         'multiply' | 'screen' | 'overlay' | 'darken' | 'lighten'
//         'color-dodge' | 'color-burn' | 'hard-light' | 'soft-light'
//         'difference' | 'exclusion' | 'hue' | 'saturation' | 'color' | 'luminosity'

Filters

ctx.filter = 'blur(4px) brightness(0.8) contrast(120%) grayscale(50%)';
ctx.filter = 'none'; // reset
// Full CSS filter syntax supported

OffscreenCanvas

// Main thread
const offscreen = new OffscreenCanvas(800, 600);
const ctx = offscreen.getContext('2d');
ctx.fillRect(0, 0, 100, 100);
const bitmap = await offscreen.transferToImageBitmap();
// Draw to on-screen canvas
mainCtx.drawImage(bitmap, 0, 0);

// Transfer to Worker (zero-copy)
const canvas = document.getElementById('c');
const offscreen2 = canvas.transferControlToOffscreen();
worker.postMessage({ canvas: offscreen2 }, [offscreen2]);

// Inside worker
onmessage = e => {
  const ctx = e.data.canvas.getContext('2d');
  // draw — commits directly to screen
};

Export / toDataURL / toBlob

canvas.toDataURL('image/png');                     // base64 PNG
canvas.toDataURL('image/jpeg', 0.8);               // JPEG quality 0–1
canvas.toDataURL('image/webp', 0.9);               // WebP

canvas.toBlob(blob => {
  const url = URL.createObjectURL(blob);
  a.href = url; a.download = 'image.png'; a.click();
}, 'image/png');

// OffscreenCanvas
const blob = await offscreen.convertToBlob({ type: 'image/webp', quality: 0.9 });

Animation Loop

let rafId;
function loop(timestamp) {
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  draw(timestamp);
  rafId = requestAnimationFrame(loop);
}
rafId = requestAnimationFrame(loop);

// Stop
cancelAnimationFrame(rafId);

ImageBitmap

const bitmap = await createImageBitmap(blob, { resizeWidth: 200, resizeHeight: 200 });
const bitmap2 = await createImageBitmap(img, sx, sy, sw, sh);
ctx.drawImage(bitmap, 0, 0);
bitmap.close(); // free memory