chart.xkcdでカスタムツールチップを実装する方法

カスタムツールチップによるインタラクティブなデータ可視化の構築

chart.xkcdは、手描き風のグラフを簡単に作成できるライブラリです。その中でもツールチップはユーザーとデータをつなぐ重要なインターフェースであり、デフォルトの表示では限界があります。この記事では、src/components/Tooltip.js をカスタマイズすることで、独自のスタイルと動作を持つツールチップを実現する方法を解説します。

ツールチップの基本構造

ツールチップは Tooltip クラスとして定義されており、コンストラクタで親要素、タイトル、データ項目、位置情報などを受け取ります。内部ではSVG要素を使って背景矩形とテキストを描画し、動的にサイズや位置を調整します。

constructor({
  parent,
  title,
  items,
  position,
  unxkcdify,
  backgroundColor,
  strokeColor,
}) {
  this.title = title;
  this.items = items;
  this.position = position;

  // SVGコンテナの作成
  this.svg = parent.append('svg')
    .attr('x', this._getUpLeftX())
    .attr('y', this._getUpLeftY())
    .style('visibility', 'hidden');

  // 背景矩形の生成
  this.tipBackground = this.svg.append('rect')
    .style('fill', backgroundColor)
    .attr('fill-opacity', 0.9)
    .attr('stroke', strokeColor)
    .attr('stroke-width', 2)
    .attr('rx', 5)
    .attr('ry', 5);
}

_getBackgroundWidth() と _getBackgroundHeight() によってコンテンツに応じたサイズが自動計算され、_getUpLeftX() / _getUpLeftY() により上左、上右、下左、下右の4パターンに対応した位置指定が可能になります。

スタイルのカスタマイズ

背景と枠線の設定

背景色や枠線の太さ、角の丸みはコンストラクタ引数で直接変更できます。例えば、青系の背景に白い枠線を適用するには以下のように記述します。

const customTooltip = new Tooltip({
  parent: chart.svg,
  title: "売上推移",
  items: [{ color: "#3498db", text: "1月: ¥12,500" }],
  position: { type: "upRight", x: 150, y: 80 },
  backgroundColor: "#3498db",
  strokeColor: "#ffffff"
});

また、rx, ry, stroke-width の値を編集することで、より柔らかい印象や強調されたデザインも可能です。

this.tipBackground
  .attr('rx', 10)
  .attr('ry', 10)
  .attr('stroke-width', 3);

テキストスタイルの改善

タイトルと各項目のテキストは、font-size, font-weight, fill などのプロパティでカスタマイズできます。統一感のある見た目にするために、テーマカラーに合わせて調整しましょう。

this.tipTitle = this.svg.append('text')
  .style('font-size', 14)
  .style('font-weight', 'bold')
  .style('fill', '#1a5f7a');

インタラクションの強化

動的更新機能

update() メソッドを使用すると、データの変化に応じてツールチップの内容を再描画できます。これはリアルタイム監視やマウス追跡などに適しています。

// 初期化
const tooltip = new Tooltip({ /* 設定 */ });

// 更新
tooltip.update({
  title: "現在の気温",
  items: [{ color: "#e74c3c", text: `${currentTemp}°C` }],
  position: { type: "upLeft", x: event.pageX, y: event.pageY }
});

このメソッドは内容の変更がある場合のみ再描画を行い、無駄なレンダリングを回避します。

表示制御

show() と hide() メソッドを使って、明示的にツールチップの表示・非表示を制御できます。これにより、マウスオーバー時の反応を自由に設計できます。

chart.svg.selectAll(".dot")
  .on("mouseover", function(event) {
    tooltip.show();
  })
  .on("mouseout", function() {
    tooltip.hide();
  })
  .on("mousemove", function(event) {
    tooltip.update({
      position: { type: "upRight", x: event.pageX, y: event.pageY }
    });
  });

高度なカスタマイズ技術

レイアウトの再設計

既存の「色ブロック + テキスト」の水平レイアウトを変更したい場合、_generateTipItem() メソッドのロジックを修正します。複数列や右側に数値を配置するような構成も可能になります。

_generateTipItem(item, index) {
  const itemSvg = this.svg.append('svg')
    .attr('x', 15)
    .attr('y', 30 + index * 25);

  // 色のアイコン
  itemSvg.append('rect')
    .attr('width', 12)
    .attr('height', 12)
    .attr('fill', item.color);

  // 主要テキスト
  itemSvg.append('text')
    .attr('x', 25)
    .attr('y', 12)
    .text(item.label);

  // 右端に数値を表示
  itemSvg.append('text')
    .attr('x', 150)
    .attr('y', 12)
    .attr('text-anchor', 'end')
    .text(item.value);
}

アニメーション効果の追加

show() と hide() に transition() を組み込むことで、フェードイン・フェードアウトのアニメーションを実現できます。

show() {
  this.svg.transition()
    .duration(300)
    .style('opacity', 1)
    .style('visibility', 'visible');
}

hide() {
  this.svg.transition()
    .duration(300)
    .style('opacity', 0)
    .on('end', () => {
      this.svg.style('visibility', 'hidden');
    });
}

実際の利用例

以下のコードは折れ線グラフにカスタムツールチップを導入した完全なサンプルです。テーマカラー、動的更新、マウスイベントとの連携をすべて含んでいます。

<html>
<head>
  <title>カスタムツールチップの実装例</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.xkcd@1.1.11/dist/chart.xkcd.min.js"></script>
</head>
<body>
  <div id="chart"></div>
  <script>
    const svg = document.querySelector("#chart");
    const chart = new chartXkcd.Line(svg, {
      title: "ユーザー増加トレンド",
      xLabel: "月",
      yLabel: "人数",
      data: {
        labels: ["1月", "2月", "3月"],
        datasets: [{ label: "新規登録", data: [120, 190, 300] }]
      }
    });

    const tooltip = new chartXkcd.Tooltip({
      parent: chart.svg,
      title: "詳細情報",
      items: [{ color: "#e74c3c", text: "読み込み中..." }],
      position: { type: "upRight", x: 0, y: 0 },
      backgroundColor: "rgba(52, 152, 219, 0.9)",
      strokeColor: "#ffffff"
    });

    chart.svg.selectAll(".dot")
      .on("mouseover", function(event, d) {
        tooltip.update({
          title: `${chart.data.labels[d.index]}のデータ`,
          items: [{
            color: "#e74c3c",
            label: "新規ユーザー数",
            value: chart.data.datasets[0].data[d.index]
          }],
          position: { type: "upRight", x: event.pageX, y: event.pageY }
        });
        tooltip.show();
      })
      .on("mouseout", () => tooltip.hide())
      .on("mousemove", (event) => {
        tooltip.update({
          position: { type: "upRight", x: event.pageX, y: event.pageY }
        });
      });
  </script>
</body>
</html>

これらのアプローチを通じて、chart.xkcdのツールチップをビジネス要件に合わせてカスタマイズでき、より直感的かつ魅力的なデータ視覚化が実現します。詳細な設定については、公式ドキュメントの docs/04-line.md および docs/06-bar.md におけるインタラクションセクションをご参照ください。

タグ: chart.xkcd SVG D3.js ツールチップ カスタムスタイル

10月12日 07:18 投稿