ReactのTSXからSVGを動的生成!Satoriで描く自由なSVGの世界

ウェブ開発の中で、SVG(Scalable Vector Graphics)の使い所は多岐にわたります。アイコンやロゴ、グラフ、ダイアグラムなど、サイズの制約を受けずに高精細な表現ができるSVGは、エンジニア・デザイナー問わず魅力的なフォーマットです。

しかし、そのSVGをコードで動的に生成しようとしたとき、従来の手法では結構面倒だったりします。SVGタグを文字列で組み立てたり、D3.jsのようなライブラリを使ったりと、手間がかかることが多かったのではないでしょうか?

そこで今回は、ReactのTSX構文をそのまま使ってSVGを生成できる、Vercel製のライブラリ「Satori」を紹介します。OGP画像生成の文脈で知られることが多いSatoriですが、実はもっと汎用的に使える“SVGジェネレーター”でもあるのです。


Satoriとは?

Satoriは、Vercelが開発したSVGレンダリングエンジンです。ReactのJSX(もしくはTSX)で記述された仮想DOMを解析し、SVG形式の文字列として出力してくれるライブラリです。

一言で言えば、**「ReactのTSXをそのままSVGに変換できるライブラリ」**です。

通常、SVGを生成するには、手動でXMLのようなSVG構造を書いたり、複雑なライブラリを使ったりする必要があります。Satoriを使えば、Reactコンポーネントとしてデザインを記述し、そのままSVGとして出力できるので、開発効率と柔軟性が格段に向上します。


なぜSatoriを使うのか?

Satoriの特筆すべき点は、以下の2つに集約されます。

  1. ReactのTSX構文でSVGを生成できる
  2. 生成されたSVGはNode.js環境で動的に出力可能

特に1が革新的で、「ReactでUIを作るようにSVGの構造も書ける」というのは、React開発者にとっては大きなメリットです。

たとえば次のようなコードがそのままSVGになります。

const element = (
  <div style={{ fontSize: 32, color: 'black', backgroundColor: 'white' }}>
    Hello, SVG World!
  </div>
)

const svg = await satori(element, {
  width: 400,
  height: 200,
  fonts: [/* フォント情報 */]
})

このように、HTML的なレイアウト感覚でSVGを組み立てることができるのです。SVGを意識せずに、React的な思考でコンポーネントを組んでいくことができます。


SVGの中身を完全に制御できる

Satoriが生成するSVGは、ベクトル形式なので画像として保存することも、ブラウザ上でインライン表示することもできます。

SVGで描ける内容は、Satoriでもかなりの範囲がサポートされています:

  • テキスト(文字列の描画)
  • 長方形、円、直線
  • 背景色
  • padding, flexboxのような一部のCSSプロパティ
  • 画像(Base64などを使えばOK)

複雑な構造をプログラム的に記述するにはやや工夫が必要ですが、TSXの構文が使えるので条件分岐やループなどのロジックも簡単です。


フォントの組み込みも自由自在

Satoriはブラウザのようにシステムフォントを自動で使うわけではありません。使用したいフォントは明示的に読み込んで渡す必要があります。

const font = fs.readFileSync('./fonts/NotoSansJP-Regular.ttf')

const svg = await satori(
  <div style={{ fontFamily: 'Noto Sans JP' }}>こんにちは、世界</div>,
  {
    width: 800,
    height: 400,
    fonts: [
      {
        name: 'Noto Sans JP',
        data: font,
        weight: 400,
        style: 'normal',
      },
    ],
  }
)

これにより、SVGの中でフォントが完全に一貫して埋め込まれるため、どの環境でも同じ見た目になります。多言語対応にも最適です。


完全にTSXベースのSVGテンプレートを作れる

Satoriの利点は、Reactコンポーネントを使ってSVGテンプレートを管理できる点です。たとえば、以下のようなコードでテンプレートをモジュール化できます。

// components/MyCard.tsx
export const MyCard = ({ title, subtitle }: { title: string; subtitle: string }) => (
  <div style={{
    display: 'flex',
    flexDirection: 'column',
    padding: '40px',
    backgroundColor: '#fefefe',
    border: '2px solid #ccc',
    borderRadius: '12px',
  }}>
    <h1>{title}</h1>
    <p>{subtitle}</p>
  </div>
)

そしてSatoriで使う:

import { MyCard } from './components/MyCard'

const svg = await satori(<MyCard title="SVG Magic" subtitle="TSXで作る自由なSVG" />, {
  width: 800,
  height: 600,
  fonts: [...],
})

まさに、UIを作る感覚でSVGテンプレートを再利用・拡張できるのです。


SatoriはOGP生成専用じゃない!

Satoriは「OGP画像生成用ツール」として語られることが多いですが、それだけに留まりません。

  • 名刺の自動生成ツール
  • プレゼン資料の一部としてSVGグラフィック出力
  • 招待状・チケット画像のカスタマイズ
  • PDFに埋め込むSVGアセットの生成
  • ブログのアイキャッチ画像、プロフィールカードなど

あらゆる「プログラムで描画したいベクター画像」のニーズに応えられる汎用的なライブラリです。むしろ、OGPに限定するにはもったいない!


出力したSVGをさらにPNGに変換したい場合

SVGをブラウザでそのまま使うのも良いですが、PNGなどのラスタ形式に変換したいケースもあると思います。Satoriで出力したSVGは、@resvg/resvg-js を使って簡単にPNG変換できます。

import { Resvg } from '@resvg/resvg-js'

const resvg = new Resvg(svg)
const pngBuffer = resvg.render().asPng()
fs.writeFileSync('output.png', pngBuffer)

実例:SVGのバッジを動的生成してみた

私は実際に、ユーザーのステータスに応じてカスタムSVGバッジを生成する仕組みを作ってみました。Reactで記述したコンポーネントに、動的に色やテキストを渡すだけで、ユーザー専用のSVGが生成され、プロフィールに組み込めるようになります。

こういったスケーラブルな画像生成は、特に個別デザインが必要なWebアプリケーションと非常に相性が良いと感じました。


file-binのご紹介:ファイル共有にもっと自由を

ちなみに、このブログで紹介してきたSVGやPNGのようなファイルを、セキュアに、かつ手軽に共有したいときに便利なのが、私たちが開発しているfile-binというサービスです。

  • ドラッグ&ドロップで即アップロード
  • 暗号化されたファイル送信(E2E対応)
  • ファイルごとにカスタムOGP設定が可能
  • ゲストも10MBまでアップロードOK
  • Proユーザーには大容量とマイページ機能も

file-binは、エンジニア向けの“セキュアなファイル共有プラットフォーム”として開発されています。Satoriで生成したSVGや画像などの成果物を、誰でも簡単に共有できる場所として、ぜひご活用ください!


まとめ

Satoriは、単なるOGP画像生成ライブラリではなく、ReactのTSX構文でSVGを動的生成できる強力なツールです。Reactの表現力とSVGのスケーラビリティが組み合わさることで、より柔軟で再利用可能なビジュアル生成が可能になります。

ぜひ皆さんも、Satoriを使ってSVGの世界を自由に描いてみてください!

そして、共有にはfile-binをお忘れなく!

コメント

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です