凡例(Legend)の配置・スタイル

凡例(Legend)は、チャート内の各データ系列が何を表しているかを示すラベル付きのインジケーター。複数系列を扱うチャートで、色やマーカーとデータの対応関係を明示するために使われる。

配置位置の変更(上・下・左・右)、ブランドに合わせたスタイリング、クリックによる系列の表示/非表示トグル、多系列時のスクロール対応。

主なバリエーション
  • 配置位置の変更(上・下・左・右・チャート内)
  • カスタムアイコン・マーカー
  • クリックによる系列の表示/非表示トグル
  • スクロール可能な凡例(多系列対応)
  • カスタムHTML/JSXでの完全置き換え

ライブラリ横断比較

機能RechartsEChartsPlotly.jsChart.jsNivoApexCharts
配置位置の変更
layout/verticalAlign/align
left/top/orient
x/y/orientation
position/align
anchor
position/horizontalAlign
カスタムアイコン/マーカー
iconType
icon
部分対応
usePointStyle
symbolShape
markers.shape
クリックで系列トグル
デフォルト対応
selectedMode
itemclick
onClick cb
toggleSerie
onItemClick
スクロール可能な凡例×
type:"scroll"
××××
カスタムHTML/JSX
content prop
×××××
スタイルカスタマイズ
style/wrapperStyle
textStyle
font/bgcolor
labels.font
theme
fontSize/labels

○ = 対応  △ = 部分対応・制限あり  × = 非対応

ライブラリ別コード例

各ライブラリで凡例をカスタマイズする際の設定部分を抜粋しています。 動くデモは各比較ページでご確認ください。

Recharts

import { Legend, LineChart, Line } from 'recharts';

// 基本的な配置設定
<LineChart data={data}>
  <Legend
    layout="horizontal"        // 'horizontal' | 'vertical'
    verticalAlign="bottom"     // 'top' | 'middle' | 'bottom'
    align="center"             // 'left' | 'center' | 'right'
    iconType="circle"          // 'line' | 'square' | 'rect' | 'circle' | 'diamond' | 'star' | 'triangle' | 'wye'
    iconSize={10}
  />
</LineChart>

// カスタムレンダラーで完全置き換え
const renderCustomLegend = (props) => {
  const { payload } = props;
  return (
    <ul className="flex gap-4 justify-center mt-2">
      {payload.map((entry, index) => (
        <li key={index} className="flex items-center gap-1 text-sm">
          <span
            style={{
              background: entry.color,
              width: 12,
              height: 12,
              borderRadius: '50%',
              display: 'inline-block',
            }}
          />
          {entry.value}
        </li>
      ))}
    </ul>
  );
};

<Legend content={renderCustomLegend} />

ECharts

// ECharts: legend オブジェクトで設定
const option = {
  legend: {
    show: true,
    type: 'plain',           // 'plain' | 'scroll'(スクロール対応・多系列向け)
    orient: 'horizontal',    // 'horizontal' | 'vertical'
    left: 'center',          // 'left' | 'center' | 'right' | px
    top: 'bottom',           // 'top' | 'middle' | 'bottom' | px

    // アイコンスタイル
    icon: 'circle',          // 'circle' | 'rect' | 'triangle' | 'roundRect' など
    itemWidth: 14,
    itemHeight: 14,

    // テキストスタイル
    textStyle: { fontSize: 12, color: '#374151' },

    // クリックで系列トグル(デフォルトで有効)
    selectedMode: true,      // true | false | 'single' | 'multiple'

    // スクロール型(多系列対応)
    // type: 'scroll',
    // pageButtonPosition: 'end',
  },
};

Plotly.js

// Plotly.js: layout.legend で設定
const layout = {
  showlegend: true,
  legend: {
    x: 0,             // 0〜1(0=左端、1=右端)
    y: 1,             // 0〜1(0=下端、1=上端)
    xanchor: 'left',
    yanchor: 'auto',
    orientation: 'h', // 'v'(縦)| 'h'(横)

    // スタイル
    bgcolor: 'rgba(255,255,255,0.8)',
    bordercolor: '#e5e7eb',
    borderwidth: 1,
    font: { size: 12, color: '#374151' },

    // アイテムクリックで系列トグル
    itemclick: 'toggle',           // 'toggle' | 'toggleothers' | false
    itemdoubleclick: 'toggleothers',
  },
};

Chart.js

// Chart.js: plugins.legend で設定
const options = {
  plugins: {
    legend: {
      display: true,
      position: 'bottom',    // 'top' | 'bottom' | 'left' | 'right' | 'chartArea'
      align: 'center',       // 'start' | 'center' | 'end'

      labels: {
        boxWidth: 12,
        boxHeight: 12,
        usePointStyle: true, // 折れ線グラフの点スタイルを使用
        padding: 16,
        font: { size: 12 },
        color: '#374151',
        // 特定系列をラベルから除外
        filter: (item) => item.text !== '非表示系列',
      },

      // クリックハンドラ(デフォルトは表示/非表示トグル)
      onClick: (e, legendItem, legend) => {
        const index = legendItem.datasetIndex;
        const ci = legend.chart;
        ci.setDatasetVisibility(index, !ci.isDatasetVisible(index));
        ci.update();
      },
    },
  },
};

Nivo

import { ResponsiveBar } from '@nivo/bar';

// legends プロップで設定(デフォルトは非表示のため明示が必要)
<ResponsiveBar
  data={data}
  keys={['series1', 'series2', 'series3']}

  legends={[
    {
      dataFrom: 'keys',          // 'keys' | 'indexes'
      anchor: 'bottom',          // 配置位置('top' | 'bottom' | 'left' | 'right' など)
      direction: 'row',          // 'row' | 'column'
      justify: false,
      translateX: 0,
      translateY: 56,
      itemsSpacing: 16,
      itemWidth: 100,
      itemHeight: 20,
      symbolSize: 12,
      symbolShape: 'circle',     // 'circle' | 'square' | 'diamond' | 'triangle'

      // クリックで系列トグル
      toggleSerie: true,
    },
  ]}
/>

ApexCharts

// ApexCharts: legend オブジェクトで設定
const options = {
  legend: {
    show: true,
    position: 'bottom',          // 'top' | 'bottom' | 'left' | 'right'
    horizontalAlign: 'center',   // 'left' | 'center' | 'right'

    // スタイル
    fontSize: '13px',
    fontFamily: 'inherit',
    labels: {
      colors: ['#374151'],
      useSeriesColors: false,
    },

    // アイコン形状
    markers: {
      size: 6,
      shape: 'circle',     // 'circle' | 'square' | 'line' | 'plus' | 'cross'
      offsetX: 0,
      offsetY: 0,
    },

    // クリックで系列トグル(デフォルトで有効)
    onItemClick: {
      toggleDataSeries: true,
    },
    onItemHover: {
      highlightDataSeries: true,
    },
  },
};

まとめ・選び方のヒント

  • JSXで完全カスタマイズしたい → Recharts(content propにReactコンポーネントを渡せる)
  • 多系列でスクロール対応が必要 → ECharts(type: 'scroll'で多系列凡例に対応)
  • クリックで系列トグルのデフォルト動作 → 全ライブラリで対応(設定方法は異なる)
  • JSON設定だけで柔軟にカスタマイズ → ECharts・ApexCharts(豊富なオプション)
  • Nivoで凡例を表示するには → legends配列を明示的に指定(デフォルトでは非表示)