lab-charts

EChartsギャラリー

カレンダー座標・タイムライン・dataZoomなど、Apache EChartsならではの表現を実データで5点。バンドルはecharts/coreと必要モジュールのみを登録するtree-shaking構成です。

東京の日平均気温カレンダー(直近1年)

カレンダー座標系のヒートマップ。季節の移り変わりが帯で見える

コードを見る
"use client";

import EChartsBase, { type EChartsOption } from "./EChartsBase";
import { CHROME, TEMP_RAMP } from "@/lib/palette";
import type { CalendarHeatmapData } from "@/lib/selectors";

export default function TempCalendarHeatmap({
  data,
}: {
  data: CalendarHeatmapData;
}) {
  const option: EChartsOption = {
    tooltip: {
      formatter: (params) => {
        const p = params as unknown as { value: [string, number] };
        return `${p.value[0]}<br/>日平均気温: ${p.value[1]}度`;
      },
    },
    visualMap: {
      min: data.min,
      max: data.max,
      type: "continuous",
      orient: "horizontal",
      left: "center",
      bottom: 0,
      inRange: { color: [...TEMP_RAMP] },
      text: [`${data.max}度`, `${data.min}度`],
      textStyle: { color: CHROME.inkSecondary },
    },
    calendar: {
      top: 40,
      left: 50,
      right: 10,
      range: data.range,
      cellSize: ["auto", 13],
      dayLabel: {
        nameMap: ["日", "月", "火", "水", "木", "金", "土"],
        color: CHROME.inkMuted,
      },
      monthLabel: {
        formatter: "{M}月",
        color: CHROME.inkMuted,
      },
      yearLabel: { show: true, color: CHROME.inkSecondary, fontSize: 12 },
      itemStyle: { borderColor: CHROME.surface, borderWidth: 2 },
      splitLine: { lineStyle: { color: CHROME.axisline, width: 1 } },
    },
    series: [
      {
        type: "heatmap",
        coordinateSystem: "calendar",
        data: data.data,
      },
    ],
  };

  return (
    <EChartsBase
      option={option}
      height={260}
      ariaLabel="東京の直近1年の日平均気温をカレンダー形式で示したヒートマップ。夏の高温期間と冬の低温期間が帯状に読み取れる"
    />
  );
}

全国人口ピラミッド(2024年10月1日現在)

年齢5歳階級・男女別の双方向棒。単位は千人

コードを見る
"use client";

import EChartsBase, { type EChartsOption } from "./EChartsBase";
import { SERIES } from "@/lib/palette";
import type { AgePyramidData } from "@/lib/selectors";

export default function AgePyramid({ data }: { data: AgePyramidData }) {
  const formatValue = (v: number) =>
    `${Math.abs(v).toLocaleString("ja-JP")}千人`;

  const option: EChartsOption = {
    tooltip: {
      trigger: "axis",
      axisPointer: { type: "shadow" },
      formatter: (params) => {
        const list = params as unknown as { seriesName: string; value: number; name: string }[];
        const lines = list.map(
          (p) => `${p.seriesName}: ${formatValue(p.value)}`,
        );
        return `${list[0].name}<br/>${lines.join("<br/>")}`;
      },
    },
    legend: { data: ["男性", "女性"], top: 0 },
    grid: { left: 70, right: 20, top: 30, bottom: 20 },
    xAxis: {
      type: "value",
      // 男性側は負値で左へ伸ばす双方向棒。目盛は絶対値で表示
      axisLabel: {
        formatter: (v: number) => `${Math.abs(v / 1000).toFixed(0)}百万`,
      },
    },
    yAxis: {
      type: "category",
      data: data.classes,
      axisLabel: { fontSize: 10 },
    },
    series: [
      {
        name: "男性",
        type: "bar",
        stack: "total",
        data: data.male.map((v) => -v),
        itemStyle: { color: SERIES[0], borderRadius: [2, 0, 0, 2] },
        barWidth: "70%",
      },
      {
        name: "女性",
        type: "bar",
        stack: "total",
        data: data.female,
        itemStyle: { color: SERIES[6], borderRadius: [0, 2, 2, 0] },
      },
    ],
  };

  return (
    <EChartsBase
      option={option}
      height={400}
      ariaLabel={`全国の年齢5歳階級別人口ピラミッド(${data.asOf}、単位${data.unit})。少子高齢化により裾が狭く中高年層が厚い形状`}
    />
  );
}

都道府県別人口の推移(上位15)

1980年から最新推計まで、タイムラインで年次を切り替え

コードを見る
"use client";

import EChartsBase, { type EChartsTimelineOption } from "./EChartsBase";
import { CHROME, SERIES } from "@/lib/palette";
import type { PrefTimelineData } from "@/lib/selectors";

export default function PrefTimelineBar({ data }: { data: PrefTimelineData }) {
  const option: EChartsTimelineOption = {
    baseOption: {
      timeline: {
        axisType: "category",
        autoPlay: false,
        playInterval: 1500,
        data: data.years.map((y) =>
          data.estimateYears.includes(y) ? `${y}(推計)` : `${y}`,
        ),
        label: { color: CHROME.inkSecondary, fontSize: 11 },
        lineStyle: { color: CHROME.axisline },
        checkpointStyle: { color: SERIES[0] },
        controlStyle: { color: CHROME.inkSecondary },
        bottom: 0,
      },
      tooltip: {
        trigger: "axis",
        axisPointer: { type: "shadow" },
        valueFormatter: (v) =>
          `${((v as number) / 10000).toLocaleString("ja-JP", { maximumFractionDigits: 1 })}万人`,
      },
      grid: { left: 70, right: 40, top: 30, bottom: 70 },
      xAxis: {
        type: "value",
        name: "人口(万人)",
        nameLocation: "middle",
        nameGap: 24,
        axisLabel: {
          formatter: (v: number) => `${(v / 10000).toLocaleString("ja-JP")}`,
        },
      },
      yAxis: { type: "category", axisLabel: { fontSize: 11 } },
      series: [{ type: "bar", itemStyle: { color: SERIES[0], borderRadius: [0, 2, 2, 0] } }],
    },
    options: data.byYear.map((y) => ({
      yAxis: { type: "category", data: y.items.map((i) => i.name) },
      series: [
        {
          type: "bar",
          name: `${y.year}年 人口`,
          data: y.items.map((i) => i.population),
        },
      ],
    })),
  };

  return (
    <EChartsBase
      option={option}
      height={420}
      ariaLabel="都道府県別人口上位15の横棒グラフ。下部のタイムラインで国勢調査の年次と最新推計を切り替えられる"
    />
  );
}

東京の月別気温・降水量(1991年〜)

雨温図形式の複合チャート。スライダーで全期間を自由に拡大

コードを見る
"use client";

import EChartsBase, { type EChartsOption } from "./EChartsBase";
import { SERIES, withAlpha } from "@/lib/palette";
import type { ClimographData } from "@/lib/selectors";

export default function TokyoClimographZoom({ data }: { data: ClimographData }) {
  const total = data.labels.length;
  // 初期表示は直近5年分にズームしておく
  const startPercent = Math.max(0, ((total - 60) / total) * 100);

  const option: EChartsOption = {
    tooltip: {
      trigger: "axis",
      axisPointer: { type: "cross" },
    },
    legend: { data: ["月降水量", "月平均気温"], top: 0 },
    grid: { left: 55, right: 55, top: 30, bottom: 70 },
    xAxis: {
      type: "category",
      data: data.labels,
      axisLabel: { fontSize: 10 },
    },
    // 雨温図の慣例に合わせた気温・降水量の2軸構成
    yAxis: [
      {
        type: "value",
        name: "降水量(mm)",
        position: "left",
        axisLabel: { formatter: "{value}" },
        splitLine: { show: true },
      },
      {
        type: "value",
        name: "気温(度)",
        position: "right",
        axisLabel: { formatter: "{value}" },
        splitLine: { show: false },
      },
    ],
    dataZoom: [
      { type: "slider", start: startPercent, end: 100, height: 24, bottom: 8 },
      { type: "inside" },
    ],
    series: [
      {
        name: "月降水量",
        type: "bar",
        yAxisIndex: 0,
        data: data.precip,
        itemStyle: { color: withAlpha(SERIES[0], 0.7), borderRadius: [2, 2, 0, 0] },
        tooltip: { valueFormatter: (v) => `${v}mm` },
      },
      {
        name: "月平均気温",
        type: "line",
        yAxisIndex: 1,
        data: data.temp,
        showSymbol: false,
        lineStyle: { color: SERIES[5], width: 2 },
        itemStyle: { color: SERIES[5] },
        tooltip: { valueFormatter: (v) => `${v}度` },
      },
    ],
  };

  return (
    <EChartsBase
      option={option}
      height={360}
      ariaLabel="東京の1991年以降の月平均気温(折れ線)と月降水量(棒)の複合チャート。下部のスライダーで期間を拡大縮小できる"
    />
  );
}

東京の月平均気温ヒートマップ(年×月)

1991年以降の全月を1枚に。近年ほど暖色が増える

コードを見る
"use client";

import EChartsBase, { type EChartsOption } from "./EChartsBase";
import { CHROME, TEMP_RAMP } from "@/lib/palette";
import { MONTH_LABELS } from "@/lib/format";
import type { MonthYearHeatmapData } from "@/lib/selectors";

export default function MonthYearHeatmap({
  data,
}: {
  data: MonthYearHeatmapData;
}) {
  const option: EChartsOption = {
    tooltip: {
      formatter: (params) => {
        const p = params as unknown as { value: [number, number, number] };
        const [yi, mi, v] = p.value;
        return `${data.years[yi]}年${mi + 1}月<br/>月平均気温: ${v}度`;
      },
    },
    grid: { left: 45, right: 10, top: 10, bottom: 70 },
    xAxis: {
      type: "category",
      data: data.years.map(String),
      axisLabel: { fontSize: 10, interval: 4 },
      splitArea: { show: false },
    },
    yAxis: {
      type: "category",
      data: [...MONTH_LABELS],
      axisLabel: { fontSize: 10 },
      inverse: true,
    },
    visualMap: {
      min: data.min,
      max: data.max,
      type: "continuous",
      orient: "horizontal",
      left: "center",
      bottom: 0,
      inRange: { color: [...TEMP_RAMP] },
      text: [`${data.max}度`, `${data.min}度`],
      textStyle: { color: CHROME.inkSecondary },
    },
    series: [
      {
        type: "heatmap",
        data: data.data,
        itemStyle: { borderColor: CHROME.surface, borderWidth: 1 },
        emphasis: { itemStyle: { borderColor: CHROME.inkPrimary, borderWidth: 1 } },
      },
    ],
  };

  return (
    <EChartsBase
      option={option}
      height={340}
      ariaLabel="東京の1991年以降の月平均気温を年×月のグリッドで示したヒートマップ。近年ほど暖色が増え、温暖化傾向が読み取れる"
    />
  );
}