この記事で学べること#
- updatemenusの実装方法(再生/一時停止ボタン)
- slidersの実装方法(シークバー)
- アニメーション制御ボタンの配置とスタイリング
- フレーム間の遷移設定
- ボタンとスライダーの連携
対象読者#
- D-4「Plotly.js Frames APIアニメーション基礎」を読んだ方
- アニメーションにユーザー操作を追加したい方
- インタラクティブなUIを構築したい方
前回の記事では、Frames APIによるアニメーションの基本を学びました。本記事では、updatemenusとslidersを使って、ユーザーがアニメーションを自由に操作できるUIを実装します。
updatemenusとslidersとは?#
updatemenus: ボタンによる操作#
updatemenusは、ボタンやドロップダウンメニューを配置する機能です。アニメーションの再生/一時停止、速度変更などを実現します。
sliders: スライダーによる操作#
slidersは、スライダー(シークバー)を配置する機能です。ユーザーが任意のフレームにジャンプできます。
基本的なupdatemenusの実装#
一時停止ボタンの追加#
最もシンプルな例として、一時停止ボタンを追加します。
const layout = {
title: '3D軌道アニメーション',
scene: {
xaxis: { title: 'X (m)' },
yaxis: { title: 'Y (m)' },
zaxis: { title: 'Z (m)' }
},
updatemenus: [{
type: 'buttons', // ボタン型
showactive: false, // アクティブ状態を表示しない
buttons: [{
label: '⏸ Pause', // ボタンラベル
method: 'animate', // アニメーション制御
args: [[null], { // nullで一時停止
frame: { duration: 0, redraw: false },
mode: 'immediate',
transition: { duration: 0 }
}]
}],
direction: 'left', // ボタンの並び方向
x: 0.1, // X座標(0-1の相対座標)
y: 0, // Y座標(0-1の相対座標)
xanchor: 'left',
yanchor: 'bottom'
}],
height: 700
};重要なプロパティ:
type: 'buttons'- ボタン型のメニューmethod: 'animate'- アニメーション制御メソッドargs: [[null], {...}]-[null]で一時停止
再生/一時停止ボタンの実装#
再生ボタンと一時停止ボタンを両方追加#
updatemenus: [{
type: 'buttons',
showactive: false,
buttons: [
{
label: '▶ Play', // 再生ボタン
method: 'animate',
args: [null, { // nullで全フレーム再生
frame: { duration: 50, redraw: true },
transition: { duration: 0 },
fromcurrent: true, // 現在のフレームから再生
mode: 'immediate'
}]
},
{
label: '⏸ Pause', // 一時停止ボタン
method: 'animate',
args: [[null], {
frame: { duration: 0, redraw: false },
mode: 'immediate',
transition: { duration: 0 }
}]
}
],
direction: 'left',
x: 0.1,
y: 0,
xanchor: 'left',
yanchor: 'bottom'
}]再生ボタンの設定:
args: [null, {...}]- 第1引数nullで全フレームを再生fromcurrent: true- 現在のフレームから再生を開始frame.duration: 50- 各フレームの表示時間(ミリ秒)
一時停止ボタンの設定:
args: [[null], {...}]- 第1引数[null]で一時停止
再生速度調整ボタンの追加#
速度オプションを提供#
updatemenus: [
{
// 一時停止ボタン(1つ目のupdatemenu)
type: 'buttons',
buttons: [{
label: '⏸ Pause',
method: 'animate',
args: [[null], {
frame: { duration: 0, redraw: false },
mode: 'immediate',
transition: { duration: 0 }
}]
}],
x: 0.1,
y: 0,
xanchor: 'left',
yanchor: 'bottom'
},
{
// 速度調整ボタン(2つ目のupdatemenu)
type: 'buttons',
showactive: true, // アクティブなボタンを強調表示
buttons: [
{
label: '× 0.5', // 0.5倍速
method: 'animate',
args: [null, {
frame: { duration: 100 }, // 100ms/フレーム
transition: { duration: 0 },
mode: 'immediate'
}]
},
{
label: '× 1', // 1倍速(標準)
method: 'animate',
args: [null, {
frame: { duration: 50 }, // 50ms/フレーム
transition: { duration: 0 },
mode: 'immediate'
}]
},
{
label: '× 2', // 2倍速
method: 'animate',
args: [null, {
frame: { duration: 25 }, // 25ms/フレーム
transition: { duration: 0 },
mode: 'immediate'
}]
}
],
x: 0.25, // 一時停止ボタンの右側に配置
y: 0,
xanchor: 'left',
yanchor: 'bottom'
}
]ポイント:
- 複数のupdatemenusを配置できます
frame.durationを変えることで速度調整- duration: 100ms(遅い)、50ms(標準)、25ms(速い)
slidersの実装#
シークバーの追加#
const frames = []; // framesは既に作成済みと仮定
const layout = {
title: '3D軌道アニメーション',
scene: {/* ... */},
sliders: [{
active: 0, // 初期位置(最初のフレーム)
steps: frames.map((frame, idx) => ({
label: `${(timeData[idx] || 0).toFixed(1)}s`, // ラベル(時刻表示)
method: 'animate',
args: [[frame.name], { // 特定のフレームにジャンプ
frame: { duration: 0, redraw: true },
mode: 'immediate',
transition: { duration: 0 }
}]
})),
x: 0.1, // スライダーのX座標
len: 0.8, // スライダーの長さ(0-1の相対値)
xanchor: 'left',
y: 0,
yanchor: 'top',
pad: { t: 50, b: 10 },
currentvalue: {
visible: true, // 現在値を表示
prefix: 'Time: ', // 表示テキストのプレフィックス
xanchor: 'right',
font: { size: 16, color: '#666' }
},
transition: { duration: 0 }
}],
height: 700
};重要なプロパティ:
active: 0- 初期位置(インデックス)steps- 各フレームへのジャンプ設定label- スライダーのラベル(時刻等)len: 0.8- スライダーの長さ(画面幅の80%)currentvalue- 現在値の表示設定
updatemenusとslidersの配置調整#
レイアウトの最適化#
複数のコントロールを配置する場合、重ならないように調整します。
const layout = {
title: '3D軌道アニメーション',
scene: {/* ... */},
// ボタン類(下部)
updatemenus: [
{
// 一時停止ボタン(左)
buttons: [{/* ... */}],
x: 0.1,
y: 0,
xanchor: 'left',
yanchor: 'bottom'
},
{
// 速度調整ボタン(中央)
buttons: [{/* ... */}],
x: 0.25,
y: 0,
xanchor: 'left',
yanchor: 'bottom'
}
],
// スライダー(下部、ボタンの上)
sliders: [{
steps: [{/* ... */}],
x: 0.1,
len: 0.8,
xanchor: 'left',
y: 0.05, // ボタンより少し上
yanchor: 'bottom',
pad: { t: 50, b: 10 }
}],
margin: { t: 50, b: 80, l: 50, r: 50 }, // マージン調整
height: 700
};配置のポイント:
- ボタン:
y: 0(最下部) - スライダー:
y: 0.05(ボタンの少し上) - マージン:
b: 80(下部に80pxの余白)
完全な実装例#
再生コントロール付きアニメーション#
// データとframesは既に作成済みと仮定
const timeData = [0.0, 0.1, 0.2, /* ... */];
const frames = [/* framesデータ */];
const layout = {
title: '3D軌道アニメーション(再生コントロール付き)',
scene: {
xaxis: { title: 'X (m)' },
yaxis: { title: 'Y (m)' },
zaxis: { title: 'Z (m)' }
},
// 再生コントロールボタン
updatemenus: [
{
type: 'buttons',
showactive: false,
buttons: [
{
label: '▶ Play',
method: 'animate',
args: [null, {
frame: { duration: 50, redraw: true },
fromcurrent: true,
transition: { duration: 0 },
mode: 'immediate'
}]
},
{
label: '⏸ Pause',
method: 'animate',
args: [[null], {
frame: { duration: 0, redraw: false },
mode: 'immediate',
transition: { duration: 0 }
}]
}
],
x: 0.1,
y: 0,
xanchor: 'left',
yanchor: 'bottom'
}
],
// シークバー
sliders: [{
active: 0,
steps: frames.map((frame, idx) => ({
label: `${timeData[idx].toFixed(1)}s`,
method: 'animate',
args: [[frame.name], {
frame: { duration: 0, redraw: true },
mode: 'immediate',
transition: { duration: 0 }
}]
})),
x: 0.1,
len: 0.8,
xanchor: 'left',
y: 0.05,
yanchor: 'bottom',
pad: { t: 50, b: 10 },
currentvalue: {
visible: true,
prefix: 'Time: ',
xanchor: 'right',
font: { size: 16, color: '#666' }
}
}],
margin: { t: 50, b: 80, l: 50, r: 50 },
height: 700
};
// グラフ描画
Plotly.newPlot('plot3d', [/* traces */], layout, { frames: frames });よくある間違いと対処法#
間違い1: argsの第1引数の指定ミス#
// ❌ 悪い例: 再生ボタンのargsが間違っている
{
label: '▶ Play',
args: [[null], {...}] // [null]は一時停止用
}問題: [null]は一時停止用です。再生にはnull(配列なし)を指定します。
対策:
// ✅ 良い例: 再生ボタン
{
label: '▶ Play',
args: [null, {...}] // nullで全フレーム再生
}間違い2: スライダーのstepsが不足#
// ❌ 悪い例: stepsが空
sliders: [{
steps: [] // 空の配列
}]問題: stepsが空だと、スライダーが表示されません。
対策: framesと対応するstepsを作成します。
まとめ#
本記事では、Plotly.js updatemenusとslidersを使ったアニメーション再生コントロールの実装方法を解説しました。
重要なポイント:
- updatemenusで再生/一時停止ボタンを追加
args: [null, {...}]で再生、args: [[null], {...}]で一時停止- slidersでシークバー(フレームジャンプ)を実装
steps配列でframesと対応させる- 配置調整で重ならないようにレイアウト
次のステップとして、サブプロットレイアウト(複数グラフの統合表示)の実装に挑戦してみましょう。
参照資料#
本記事の執筆にあたり、以下の資料を参照しました [@plotly_js_docs_animations_2025; @plotly_js_docs_custom_buttons_2025; @plotly_js_docs_sliders_2025]。