[Recharts]svgにHTMLタグを組み込む

Reactのチャートライブラリ「Recharts」のLineChartで上の箇所に、任意の位置でテキストを追加したかった。

課題になったのは、Rechartsのテキストを表示したい箇所は、svgで表示する仕様になっていた点である。
要件の一つに、テキストを特定の長さ以上になったら3点リーダーで表示したいということがあった。
svgだと、CSSでテキスト省略ができず、JavaScriptで頑張ったのだが、foreignObjectを使えばSVGにHTMLタグを組み込めることができることを知った。

その整理を記載する。

LineChartにそのまま表示する。

LineChartを公式に従ってそのまま表示してみる。
<text>、<tspan>はsvgの中でテキストを扱うための要素です。
そのため、ただテキストを描画するだけならこれでOK。
可変するテキストに合わせて対応するのには向かない(JavaScriptしかない。)

<LineChart data={data} margin={chartMargin}>
  <text
    x={15}
    y={25}
    fill="black"
    textAnchor="left"
    dominantBaseline="central"
    style={{
      display: "block",
      whiteSpace: "nowrap",
      overflow: "hidden",
      textOverflow: "ellipsis",
    }}
  >
    <tspan fontSize={16} fontWeight={700}>
      {chartTitle}
    </tspan>
  </text>
  <Line
    type="linear"
    dataKey="count"
    stroke="#0096FA"
    dot={false}
    strokeWidth={2}
  />
</LineChart>

foreignObjectを使用してsvgにHTMLを組み込む

JavaScriptで書くと長くなるし、重くもなる。
CSSでかけないかな、と検討した時にforeignObjectを知る。
これを使うことで、svgの中にHTMLを埋め込むことが可能です。

foreignObjectタグの中でstyled-componentで定義したContainerとChartTitleをそのまま使用することができます。

<LineChart data={data} margin={chartMargin}>
  <foreignObject y={12} width="100%" height="200">
    <Container>
      <ChartTitle>{chartTitle}</ChartTitle>
    </Container>
  </foreignObject>
  <Line
    type="linear"
    dataKey="count"
    stroke="#0096FA"
    dot={false}
    strokeWidth={2}
  />
</LineChart>

Summary

svgの中では制約が大きく、できることも工夫しながらが多かったのですが、foreignObjectを知ってからは、できることの幅が広がったと思います。

分からないことがあったら、調べる、人に聞く、これはとても大切ですね。

シェア!

この記事を書いた人

kenichiのアバター kenichi エンジニア・写真家 | Engineer and photographer

日本全国と海外を旅するノマドワーカー。5年間、技術営業として働いたのち独立。
フリーランスエンジニアとしてWebサイト制作やアプリケーション開発を行う。面白い人たちの面白いを世に届けるべく行動中。
2024年11月にポルトガルへ移住🇵🇹