GASで動的なグラフや地図をSVGとして生成したものの、それを画像として保存したり共有したりする方法が見つからず、困ったことはありませんか?
GASはGoogleのサーバー上で動作する「ヘッドレス」な環境であるため、ベクトルデータをラスタライズ(画像化)するためのレンダリングエンジンを標準で持っていません。しかし、「ユーザーのブラウザをレンダリングエンジンとして借りる」というアプローチでこの問題を解決できます。
この方法を使えば、スプレッドシート等のデータからSVGを自在に生成・加工し、PNG形式に変換して保存できます。
CloudConvertのような外部サービスに頼ることなく、Googleスライドへの画像挿入を自動化できるのが最大の強みです。大量に使用しても追加コストはかかりませんし、何より機密データを外部のサーバーに送る必要がないため、プライバシーやセキュリティの観点からも安全です。
仕組み
1. GAS(サーバー側): SVG文字列を生成・編集する。
2. HTML(クライアント側): HtmlService でダイアログを開き、ブラウザの Canvas API を使ってSVGを描画する。
3. Canvas(クライアント側): 描画内容を Base64 形式のPNGデータに変換する。
4. GAS(サーバー側): 送り返されたデータをデコードし、Googleドライブに保存する。
実装方法
1. Code.gs (サーバーサイド)
データフローとファイルの保存を行います。
/**
* Main function to trigger the conversion
*/
function startConversion() {
const svgString = '<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><circle cx="100" cy="100" r="80" fill="red" /></svg>';
const fileName = "converted_image.png";
const template = HtmlService.createTemplateFromFile('converter');
template.svgData = svgString;
template.fileName = fileName;
const html = template.evaluate().setWidth(400).setHeight(300);
SpreadsheetApp.getUi().showModalDialog(html, 'Converting SVG to PNG...');
}
/**
* Saves the Base64 data received from the client
*/
function saveImage(base64Data, fileName) {
const decoded = Utilities.base64Decode(base64Data.split(',')[1]);
const blob = Utilities.newBlob(decoded, 'image/png', fileName);
DriveApp.createFile(blob);
return "Success";
}
2. converter.html (クライアントサイド)
同じプロジェクト内にこのファイルを作成してください。描画エンジンとして機能します。
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" style="display:none;"></canvas>
<script>
window.onload = function() {
// Data passed from GAS
const svgString = `<?!= svgData ?>`;
const fileName = `<?!= fileName ?>`;
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const img = new Image();
// Important: Ensure the SVG has the correct namespace
let blob = new Blob([svgString], {type: 'image/svg+xml;charset=utf-8'});
let url = URL.createObjectURL(blob);
img.onload = function() {
canvas.width = img.width || 1200; // Set high res
canvas.height = img.height || 1200;
ctx.fillStyle = "white"; // Optional: background color
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
const pngData = canvas.toDataURL('image/png');
google.script.run
.withSuccessHandler(() => google.script.host.close())
.saveImage(pngData, fileName);
};
img.src = url;
};
</script>
</body>
</html>
実装のポイントと注意点
1. 名前空間 (xmlns) の付与
SVGタグには必ず xmlns=”http://www.w3.org/2000/svg” が含まれている必要があります。これが欠けていると、ブラウザはSVGを「画像」として認識できず、変換に失敗します。
2. フォントの読み込み待機
Google Fontsなどを使用している場合、Canvasに描画する瞬間にフォントの読み込みが完了していないと、デフォルトフォントで書き出されてしまいます。document.fonts.ready などを利用して、フォントが準備できてから描画を開始するのがコツです。
3. 日本語文字化け対策
SVG内に日本語が含まれる場合、単純な文字列操作だとエンコードエラーが起きることがあります。クライアント側でBase64化する際は、UTF-8に対応したエンコード処理を挟むのが安全です。
まとめ
外部の有料変換APIを使わなくても、GASの HtmlService とブラウザの標準機能(Canvas API)を組み合わせるだけで、高精度な画像変換が可能です。「サーバーでできないなら、クライアントにやらせる」という発想が、GAS開発の幅を大きく広げてくれます。