โšกToolZip
๋ธ”๋กœ๊ทธ๐Ÿ› ๏ธ ๋„๊ตฌ ์‚ฌ์šฉํ•˜๊ธฐ
โ† Blog
๐Ÿ”ง utilOctober 2, 2026

Generating Thumbnail Images in the Browser with Canvas API

#javascript#canvas#webdev#toolzip

Generating Thumbnail Images in the Browser with Canvas API

Blog thumbnail generators are usually server-side โ€” send text, get back an image. I built one that runs entirely in the browser using Canvas. Here's what's actually hard about it.

Korean Web Font Loading

Korean fonts are large (often 3โ€“10MB for a complete character set). Loading them for Canvas requires waiting for them to be ready:

async function loadWebFonts() {
  const link = document.createElement('link');
  link.rel = 'stylesheet';
  link.href = 'https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@700;900&display=swap';
  document.head.appendChild(link);
  await document.fonts.ready;
}

document.fonts.ready waits for all pending font loads to complete. Without this, Canvas renders text with the fallback font.

Text Wrapping

Canvas fillText() doesn't wrap. You have to implement it:

function getWrappedLines(ctx, text, maxWidth) {
  const words = text.split(' ');
  const lines = [];
  let current = '';

  for (const word of words) {
    const test = current ? `${current} ${word}` : word;
    if (ctx.measureText(test).width > maxWidth && current) {
      lines.push(current);
      current = word;
    } else {
      current = test;
    }
  }
  if (current) lines.push(current);
  return lines;
}

Important: measure line count before drawing the background box, not after. Otherwise the text overflows the box.

Blurred Image Background

Taking a user's photo and using it as a blurred background is the most visually impressive feature:

async function drawBlurredBackground(ctx, imageFile, width, height, blur, dimOpacity) {
  const img = await loadImage(imageFile);
  const scale = Math.max(width / img.width, height / img.height);
  const sw = img.width * scale;
  const sh = img.height * scale;
  const sx = (width - sw) / 2;
  const sy = (height - sh) / 2;

  ctx.filter = `blur(${blur}px)`;
  ctx.drawImage(img, sx, sy, sw, sh);
  ctx.filter = 'none';

  // Darken overlay
  ctx.fillStyle = `rgba(0,0,0,${dimOpacity})`;
  ctx.fillRect(0, 0, width, height);
}

High-Resolution Download

The canvas preview is scaled down for display (0.5x). For download, render at full resolution:

function downloadFullRes(previewCanvas, targetWidth, targetHeight, format) {
  const out = document.createElement('canvas');
  out.width = targetWidth;
  out.height = targetHeight;
  const ctx = out.getContext('2d');
  // Scale up from preview
  ctx.scale(targetWidth / previewCanvas.width, targetHeight / previewCanvas.height);
  ctx.drawImage(previewCanvas, 0, 0);
  ctx.setTransform(1, 0, 0, 1, 0, 0);

  out.toBlob(blob => {
    const a = document.createElement('a');
    a.href = URL.createObjectURL(blob);
    a.download = `thumbnail.${format}`;
    a.click();
  }, format === 'jpg' ? 'image/jpeg' : 'image/png', 0.95);
}

Try it at toolzip.app/tools/thumbnail-maker.

๐Ÿ› ๏ธ
Try the tool now
No install ยท Free ยท No server upload
Open tool โ†’
Generating Thumbnail Images in the Browser with Canvas API โ€” ToolZip | ToolZip