グラフと動画の再生位置を連動
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
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';
どうですか?今回の内容分かりましたか?
ドンマイ!頑張りましょう!