JavaScript で SVG から PNG (Base64) へ変換

JavaScript で SVG から PNG (Base64) へ変換

Takahiro Iwasa
(岩佐 孝浩)
Takahiro Iwasa (岩佐 孝浩)
2 min read
JavaScript RxJS

RxJS を使用して SVG を PNG (Base64) に変換するコードを書きました。

この投稿のサンプルは、 GitHub リポジトリから取得できます。

画像は以下の順序で処理されます。

  1. canvas 要素作成。キャンバスが低品質の画像を生成する場合は、品質向上のためにスケーリング係数を指定してください。
  2. Image オブジェクト作成
  3. SVG を Base64 に変換
  4. Base64 を Image#src に設定
  5. 画像の読み込み後に画像をキャンバス上にレンダリング
  6. toDataURL を使用してデータURI を取得
import { filter, fromEvent, map, Observable, take, throwIfEmpty } from 'rxjs';

/**
 * Convert SVG to PNG (Base64).
 *
 * @param svgElement
 * @param scale A scaling coefficient
 * @return Observable<string>
 */
export const svgToPng = (svgElement: SVGSVGElement, scale = 4): Observable<string> => {
  const canvas = createCanvas(svgElement, scale);
  const image = new Image();

  const source = fromEvent(image, 'load').pipe(
    take(1),
    map(() => canvas.getContext('2d', {})),
    throwIfEmpty(),
    filter(Boolean),
    map((context) => {
      context.drawImage(image, 0, 0, canvas.width, canvas.height);
      return canvas.toDataURL('image/png', 1);
    }),
  );

  image.src = svgToBase64(svgElement);
  return source;
}

const createCanvas = (svgElement: SVGSVGElement, scale = 4): HTMLCanvasElement => {
  const canvas = document.createElement('canvas');
  canvas.width = svgElement.width.baseVal.value * scale;
  canvas.height = svgElement.height.baseVal.value * scale;
  return canvas;
};

const svgToBase64 = (svgElement: SVGSVGElement): string => {
  const svg = new XMLSerializer().serializeToString(svgElement);
  const base64 = window.btoa(unescape(encodeURIComponent(svg)));
  return `data:image/svg+xml;charset=utf-8;base64,${base64}`;
};
Takahiro Iwasa
(岩佐 孝浩)

Takahiro Iwasa (岩佐 孝浩)

Software Developer at iret, Inc.
主に AWS を利用したクラウドネイティブアプリケーションの設計および開発をしています。 Japan AWS Top Engineers 2020-2023