グラフと動画の再生位置を連動

Vue.jsでグラフと動画の再生位置を連動するプログラムに挑戦してみました!
今回はVue3、Nuxt3、TypeScriptの組み合わせで実装しています。
下記コマンドでインストールします。
npx nuxi init my-nuxt3-project
cd my-nuxt3-project
npm install

動画の再生は hls.js、グラフはc3.jsのJavaScriptライブラリを使用しているのでインストールします。
npm install c3 d3 hls.js

※この記事は2025/09/01時点の情報です。

components/ChartWithVideo.vue

<template>
  <div>
    <!-- グラフ表示 -->
    <div ref="chartContainer"></div>

    <!-- 動画表示 -->
    <div class="video-wrapper">
      <video ref="videoPlayer" controls width="640" height="360"></video>
    </div>
  </div>
</template>

<script setup lang="ts">
import 'c3/c3.min.css';
import Hls from "hls.js";

const chartContainer = ref<HTMLDivElement | null>(null);
const videoPlayer = ref<HTMLVideoElement | null>(null);

const videoSrc = "/sample.m3u8"; // public 配下 or 外部URL

onMounted(async () => {
  // c3 をクライアントでのみ動的 import
  const c3 = await import("c3");

  // データ作成 (0〜600秒まで60秒刻み)
  const timePoints = Array.from({ length: 21 }, (_, i) => i * 30); // [0,30,60,...,300]
  const salesData = timePoints.map(() => Math.floor(Math.random() * 500) + 50); // 50〜550
  const trendData = timePoints.map(() => Math.floor(Math.random() * 100) + 10); // 10〜110

  const chart = c3.generate({
    bindto: chartContainer.value!,
    size: {
      width: 700,   // グラフの幅
      height: 200,  // グラフの高さ
    },
    data: {
      x: "x",
      columns: [
        ["x", ...timePoints],
        ["sales", ...salesData],
        ["trend", ...trendData],
      ],
      types: {
        sales: "bar",
        trend: "line",
      },
      onclick: (d: any) => {
        if (videoPlayer.value) {
          videoPlayer.value.currentTime = d.x; // クリック位置にシーク
          videoPlayer.value.play();
        }
      },
    },
    axis: {
      x: {
        label: "時間 (秒)",
        tick: { values: timePoints },
      },
      y: { label: "値" },
    },
    bar: {
      width: { ratio: 0.8 },
    },
    tooltip: {
      grouped: true,
    },
    legend: {
      position: "right",
    },
    color: {
      pattern: ["#4dabf7", "#f59f00"], // 青とオレンジで見やすく
    },
  });

  // HLS.js のセットアップ
  if (videoPlayer.value) {
    if (Hls.isSupported()) {
      const hls = new Hls();
      hls.loadSource(videoSrc);
      hls.attachMedia(videoPlayer.value);
    } else if (videoPlayer.value.canPlayType("application/vnd.apple.mpegurl")) {
      videoPlayer.value.src = videoSrc;
    }
  }
});
</script>

<style scoped>
.video-wrapper {
  margin-top: 20px;
}
</style>

pages/Hls2.vue

<template>
  <div class="page">
    <h1>複合グラフ + HLS動画</h1>
    <ChartWithVideo />
  </div>
</template>

<script setup lang="ts">
// 先ほどのコンポーネントをインポート
import ChartWithVideo from "~/components/ChartWithVideo.vue";
</script>

<style scoped>
.page {
  padding: 20px;
}
</style>

クリックしたグラフの位置と連動して動画の再生位置を変更できました。 ちなみにc3.jsをインポートしている箇所で「モジュール 'c3' の宣言ファイルが見つかりませんでした」というエラーになる場合は src/typesフォルダにc3.d.tsファイルを作成し、以下の行を追加すればエラーが消えると思います。
declare module 'c3';

どうですか?今回の内容分かりましたか?

グラフと動画の再生位置を連動するプログラムを覚えられましたか?

ドンマイ!頑張りましょう!

管理人情報