はじめに
SVG の foreginObject 要素を使って SVG に HTML コンテンツを埋め込む方法を記載します。
foreginObject を使うことで SVG の要素だけでは実現できないよりリッチなUI表現が実現できます。
開発環境
開発環境は以下の通りです。
- Windows 11
- Chrome 131
- TypeScript 5.7.3
- React 18.3.1
- Vite 5.4.14
- Node.js 22.13.1
- npm 11.0.0
foreginObject を使わない例
比較のため、まずは foreginObject を使わない SVG のコードを実装します。
foreginObject を使わないので、SVG の要素のみでテキストや円を表現しています。
SvgWithoutForeignObject.tsx
import { FC } from "react";
const SvgWithoutForeignObject: FC = () => {
return (
<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
{/* Background rectangle */}
<rect x="10" y="10" width="380" height="180" fill="lightblue" />
{/* Simple SVG text */}
<text x="20" y="50" fontSize="16" fill="darkblue">
This is a plain SVG text.
</text>
{/* Circle with text inside */}
<circle cx="200" cy="100" r="50" fill="orange" />
<text x="200" y="105" fontSize="14" textAnchor="middle" fill="white">
Circle
</text>
</svg>
);
};
export default SvgWithoutForeignObject;
foreginObject を使った例
foreginObject を使うことで、HTML 要素を SVG 要素内で使用することができます。HTML 要素を使用することができるので、ボタンなどインターラクティブ要素を埋め込むこともできます。
SvgWithoutForeignObject.tsx
import { FC } from "react";
const SvgWithForeignObject: FC = () => {
return (
<svg width="400" height="200" xmlns="http://www.w3.org/2000/svg">
{/* Background rectangle */}
<rect x="10" y="10" width="380" height="180" fill="lightblue" />
{/* foreignObject containing HTML content */}
<foreignObject x="20" y="20" width="360" height="160">
<div
style={{
fontSize: "16px",
color: "darkblue",
padding: "10px",
backgroundColor: "white",
border: "1px solid gray",
borderRadius: "8px",
}}
>
<p>This is HTML inside SVG!</p>
<button
style={{
padding: "8px",
border: "none",
backgroundColor: "orange",
color: "white",
borderRadius: "4px",
cursor: "pointer",
}}
onClick={() => alert("Button clicked!")}
>
Click Me
</button>
</div>
</foreignObject>
</svg>
);
};
export default SvgWithForeignObject;