ガントチャート(Frappe Gantt)— JSONデータ読み込み
このコンポーネントについて
ガントチャートは、複数タスクの開始日・終了日を横軸の時間に沿って表示し、プロジェクトの全体像を共有するためのUIです。このページでは、Frappe Gantt v1.2.2をCDNで読み込み、JSONファイルから取得したタスク配列を渡して工程表を表示します。Day・Week・Monthのボタンで表示単位を切り替え、バーをドラッグまたはリサイズして日程を動かすこともできます。デモでの変更は画面表示だけで、JSONやサーバーへは保存しません。
- JSON fetchでタスクを分離 — タスク名・開始日・終了日をJSONで管理し、表示ロジックと分ける
- 最小構成で描画 —
id、name、start、endを持つ配列をnew Gantt()へ渡す - 表示モード切替 — Day / Week / Monthのボタンから
change_view_mode()を呼び出す - 標準のドラッグ・リサイズ — バーを操作して日程を変えられる。保存処理は別途API連携が必要
実装のポイント・注意点
Frappe GanttはJavaScriptだけでなくCSSも読み込まないと、タスクバーや時間軸の表示が崩れます。CDNは@1.2.2を付けて固定し、ライブラリ更新によって掲載コードの挙動が変わらないようにします。タスクをJSONファイルへ分けると、画面のコードを触らずに工程データだけを差し替えられます。
fetchはfile://で開いたHTMLからは利用できません。コピーしたサンプルはVS Code Live Serverなどのローカルサーバー経由で開いてください。ドラッグ後の変更を実運用で保存したい場合は、on_date_changeで受け取った日付をAPIへ送信します。本ページでは保存、進捗率、依存関係を扱わず、基本の表示と操作に絞っています。
HTML・CSS・JavaScriptで実装しており、Frappe Ganttライブラリ(CDN)を追加するだけで動きます。フレームワーク不要でコピペすぐに使えます。
デモ
サイト公開プロジェクト
表示単位を切り替え、タスクバーをドラッグまたは端をリサイズしてみてください。
タスクを読み込んでいます…
タスクを読み込んでいます…
サンプルソース
4つのファイルを同じフォルダに保存し、ローカルサーバー(VS Code Live Serverなど)経由でindex.htmlを開くと動作確認できます。
ファイル名:index.html / style.css / script.js / data/data.json — 保存時の文字コードはUTF-8を指定してください。
⚠️ fetchはfile://では動作しません。ローカルサーバー経由(http://)で開いてください。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ガントチャート サンプル</title>
<link rel="stylesheet" href="./style.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/frappe-gantt.css">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/frappe-gantt.umd.js"></script>
</head>
<body>
<main class="gantt-demo">
<h1>サイト公開プロジェクト</h1>
<div class="view-controls" aria-label="表示単位を切り替える">
<button type="button" data-view-mode="Day" aria-pressed="false">Day</button>
<button type="button" data-view-mode="Week" aria-pressed="true">Week</button>
<button type="button" data-view-mode="Month" aria-pressed="false">Month</button>
</div>
<div class="gantt-scroll" tabindex="0" aria-label="サイト公開プロジェクトのガントチャート">
<p id="loading">タスクを読み込んでいます…</p>
<div id="gantt-chart" aria-busy="true"></div>
</div>
<p id="status" role="status" aria-live="polite"></p>
</main>
<script src="./script.js"></script>
</body>
</html>
body {
margin: 0;
padding: 24px;
color: #1A2332;
font-family: sans-serif;
background: #F4F6F9;
}
.gantt-demo {
max-width: 960px;
margin: 0 auto;
padding: 24px;
background: #FFFFFF;
border: 1px solid #D0D7E0;
border-radius: 8px;
}
.view-controls {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 16px 0;
}
.view-controls button {
min-height: 40px;
padding: 8px 16px;
border: 1px solid #AFC1D6;
border-radius: 6px;
background: #FFFFFF;
color: #24486F;
font: inherit;
font-weight: 700;
cursor: pointer;
}
.view-controls button[aria-pressed="true"] {
border-color: #1554A0;
background: #2B7FE8;
color: #FFFFFF;
}
.gantt-scroll {
overflow-x: auto;
padding: 12px;
border: 1px solid #D0D7E0;
border-radius: 8px;
}
#gantt-chart,
#loading {
min-width: 720px;
min-height: 220px;
}
#loading {
display: flex;
align-items: center;
justify-content: center;
margin: 0;
color: #5A6A7A;
}
#loading[hidden] {
display: none;
}
var ganttInstance = null;
var chartElement = document.getElementById('gantt-chart');
var loadingElement = document.getElementById('loading');
var statusElement = document.getElementById('status');
var viewButtons = Array.prototype.slice.call(document.querySelectorAll('[data-view-mode]'));
fetch('./data/data.json')
.then(function (response) {
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
return response.json();
})
.then(function (data) {
if (!Array.isArray(data.tasks)) {
throw new Error('tasks配列が見つかりません');
}
ganttInstance = new Gantt('#gantt-chart', data.tasks, {
view_mode: 'Week',
scroll_to: 'start',
readonly_dates: false,
readonly_progress: true,
on_date_change: function () {
statusElement.textContent = '日程を変更しました。このデモでは変更を保存しません。';
}
});
chartElement.setAttribute('aria-busy', 'false');
loadingElement.hidden = true;
statusElement.textContent = 'タスクバーをドラッグまたは端をリサイズして、日程を動かせます。変更は保存されません。';
})
.catch(function (error) {
console.error('ガントチャートのタスク取得に失敗しました:', error);
loadingElement.hidden = true;
statusElement.textContent = 'タスクを読み込めませんでした。ローカルサーバー経由で開いているか確認してください。';
});
viewButtons.forEach(function (button) {
button.addEventListener('click', function () {
if (!ganttInstance) return;
var viewMode = button.dataset.viewMode;
ganttInstance.change_view_mode(viewMode, true);
viewButtons.forEach(function (item) {
item.setAttribute('aria-pressed', String(item === button));
});
statusElement.textContent = viewMode + '表示に切り替えました。';
});
});
{
"tasks": [
{ "id": "requirements", "name": "要件整理", "start": "2026-08-03", "end": "2026-08-07" },
{ "id": "design", "name": "画面設計", "start": "2026-08-10", "end": "2026-08-19" },
{ "id": "content", "name": "コンテンツ作成", "start": "2026-08-12", "end": "2026-08-28" },
{ "id": "development", "name": "実装", "start": "2026-08-20", "end": "2026-09-04" },
{ "id": "testing", "name": "動作確認", "start": "2026-09-07", "end": "2026-09-11" },
{ "id": "release", "name": "公開", "start": "2026-09-14", "end": "2026-09-15" }
]
}
AI用プロンプト
以下のプロンプトをコピーしてAIに渡すと、同様のガントチャートを生成できます。
ChatGPTやClaudeに渡し、タスク名・日付・表示モードなどの要件を追記して使うのがおすすめです。
※ このプロンプトを使ってもデモとまったく同じ動作にならない場合があります。AIの解釈や生成タイミングによって差が出ることをご了承ください。
💡 日本語の月名・日付表示を調整したい場合は、Frappe Ganttのロケール設定と表示形式もあわせて指定してください。
Frappe Gantt — JSONデータ読み込み
# ガントチャート(Frappe Gantt)作成依頼
## 概要
Frappe Gantt v1.2.2をCDNから読み込み、外部JSONのタスクデータをfetchして表示するガントチャートを実装してください。
## 要件
- HTML / CSS / バニラJavaScriptで実装する
- CSS: https://cdn.jsdelivr.net/npm/[email protected]/dist/frappe-gantt.css
- JS: https://cdn.jsdelivr.net/npm/[email protected]/dist/frappe-gantt.umd.js
- data/data.jsonをfetchし、tasks配列をnew Gantt()に渡す
- タスクはid、name、start、endを持たせる
- 初期表示はWeek、開始位置は最初のタスクに合わせる
- Day / Week / Monthボタンでchange_view_mode()を呼び出す
- 選択中のボタンはaria-pressedと見た目の両方で分かるようにする
- タスクバーのドラッグ・リサイズを有効にする
- 日程変更時は「このデモでは変更を保存しません」と表示する
- API保存、localStorage、進捗率、タスク依存関係は実装しない
- 読み込み中・取得失敗時のメッセージを表示する
- 動的メッセージはtextContentで更新する
- 小画面では横スクロールできるようにする
## 出力形式
index.html、style.css、script.js、data/data.jsonを分けて出力してください。
fetchを使うため、ローカルサーバー経由で開く必要があることも説明してください。