😽
インタラクティブ・マインドマップのプロンプト
「インタラクティブ・マインドマップ」を、生成AIに作らせるための、非常に効果的なプロンプトをご紹介します。
このプロンプトで、何ができる?
このプロンプトを使うと、以下のようなWebページをAIが自動で生成します。
3D空間に浮かぶ、動くマインドマップ: 全体像と情報のつながりが一目でわかります。
クリックで枝が展開: 興味のある項目をクリックすると、下位の項目がアニメーションしながら展開します。


詳細スライドで深掘り: さらに詳しく知りたい項目をクリックすると、全画面で詳細な解説が表示されます。
このように、情報の「全体像」と「詳細」を自由に行き来できる、新しいプレゼンテーション体験を創出できます。
魔法のプロンプト:これをコピーしてAIに貼り付けよう!
指示プロンプト:インタラクティブ・マインドマップグラレコの作成
# 概要これから、情報の全体像把握と詳細の深掘りをシームレスに体験できる、インタラクティブなWebページを作成します。このページは、中央のテーマから思考が枝分かれしていく「マインドマップ」と、クリックによって詳細情報が展開される「プレゼンテーションスライド」を融合させたものです。
# コンセプトユーザー体験は、以下の2つのフェーズで構成されます。
探索フェーズ: ユーザーは、3D空間に浮かぶマインドマップの全体像を眺め、興味のある項目をクリックして、その下位項目を複数階層にわたって展開させます。
学習フェーズ: 展開された最下位の項目をクリックすると、その項目の詳細な解説が書かれたスライドが全画面で表示され、ユーザーは内容に集中できます。
この2つのフェーズを自由に行き来できる、直感的で没入感のある学習・プレゼンテーションツールを目指します。
# 必須となる視覚効果とインタラクション以下の仕様を正確に実装してください。
3D空間とカメラワーク:ページ全体をCSSのperspectiveで3D空間として定義します。マインドマップ全体を内包するコンテナ(例: .camera-rig)を用意し、そのtransformプロパティをJavaScriptで操作することで、ズームイン・ズームアウトやパン(視点移動)といったカメラワークを実現してください。
マインドマップの段階的展開:初期状態では、中央のトピックと主要なブランチのみが表示されています。ユーザーが展開可能な項目をクリックすると、その項目にカメラが寄り、関連する下位の枝と、それらを繋ぐ線がアニメーションしながら表示されるようにしてください。展開された項目を再度クリックすると、下位の枝が格納され、カメラが元の位置に戻るように実装してください(トグル機能)。
テーマ別背景の切り替え:最上位のブランチ(例:「フロントエンド」)が展開される際、そのテーマを象徴する背景画像にページ全体が滑らかに切り替わるようにしてください。実装には、bodyタグにテーマ別のクラス(例: .bg-frontend)を付け外しする方法を推奨します。
詳細情報スライドの表示 (学習フェーズ) 📜:展開された最下位の枝(例: 「HTML」ノード 🖱️)をクリックすると、その項目の詳細な解説が書かれたスライド(モーダルウィンドウ)が、画面の最前面にアニメーション✨しながら表示されるようにしてください。この時、背景のマインドマップは後方へ下がり、少しぼやける(filter: blur())演出 🌫️ を加えて、ユーザーの意識をスライドに集中させてください。スライドには「閉じる」または「マップに戻る」ボタン ↩️ を設置し、クリックするとスライドが消え、元のマインドマップ表示に戻るようにしてください。
# 推奨されるHTML構造とCSS設計HTML:カメラワークを制御するためのラッパー要素(.camera-rig)と、マインドマップ自体を描画するキャンバス要素(.presentation-canvas)を分離することを推奨します。各ノードには、親子関係やブランチ名を識別するためのdata-*属性(例: data-branch, data-parent, data-sub-node)を付与してください。
CSS:各インタラクションの状態(ブランチ展開、スライド表示など)は、JavaScriptでクラスを付け外しすることで制御してください。(例: .branch-open, .slide-visible)アニメーションは、CSSのtransitionや@keyframesを駆使して、滑らかで心地よいものにしてください。
# サンプル実装以下に、上記仕様を完全に満たした実装サンプルを示します。これを参考に、同様の体験を再現してください。<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>詳細展開型マインドマップグラレコ(改)</title>
<!-- Google Fontsからフォントを読み込む -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Yusei+Magic&family=Noto+Sans+JP:wght@400;700&display=swap" rel="stylesheet">
<style>
/* --- 基本的なリセットと設定 --- */
body {
margin: 0;
font-family: 'Noto Sans JP', sans-serif;
background-color: #e8f0fe;
color: #334;
min-height: 100vh;
overflow: hidden;
transition: background-image 1.2s ease-in-out;
background-size: cover;
background-position: center;
}
body.bg-frontend { background-image: url('https://images.unsplash.com/photo-1555099962-4199c345e541?q=80&w=2070&auto=format&fit=crop'); }
body.bg-backend { background-image: url('https://images.unsplash.com/photo-1592609931095-54a2168ae893?q=80&w=2070&auto=format&fit=crop'); }
body.bg-tools { background-image: url('https://images.unsplash.com/photo-1581090464777-f3220bbe1b8b?q=80&w=1887&auto=format&fit=crop'); }
/* --- 全体を包むコンテナ --- */
.main-container {
position: relative;
width: 100vw;
height: 100vh;
perspective: 1500px;
}
/* --- カメラワークを制御するラッパー --- */
.camera-rig {
position: absolute;
width: 100%;
height: 100%;
transform-style: preserve-3d;
transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1);
}
/* --- マインドマップのキャンバス --- */
.presentation-canvas {
position: absolute;
width: 1400px; /* キャンバスを拡張 */
height: 1000px; /* キャンバスを拡張 */
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
transition: transform 0.8s cubic-bezier(0.4, 0, 0.2, 1), filter 0.8s ease;
}
.presentation-canvas.focused {
transform: translate(-50%, -50%) scale(0.7) translateZ(-500px);
filter: blur(5px);
}
/* --- 各ノード(情報の塊)の共通スタイル --- */
.gr-node {
position: absolute;
padding: 1rem 1.5rem;
background-color: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(5px);
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.1);
border: 2px solid #334;
text-align: center;
opacity: 0;
transform: scale(0.8);
transition: opacity 0.5s ease, transform 0.5s ease, box-shadow 0.3s ease;
cursor: pointer;
}
.gr-node.visible { opacity: 1; transform: scale(1); }
.gr-node:not([data-sub-node]):hover { transform: scale(1.05); }
.gr-node[data-branch]:hover { box-shadow: 0 8px 25px rgba(45, 115, 255, 0.3); }
.gr-node h3 { font-family: 'Yusei Magic', sans-serif; margin: 0 0 0.5rem 0; font-size: 1.2rem; }
.gr-node p { margin: 0; font-size: 0.85rem; line-height: 1.6; color: #556; }
/* ノードの配置 */
#central-topic { top: 450px; left: 600px; width: 200px; padding: 1.5rem; border-width: 4px; cursor: default; }
#branch-frontend, #branch-backend, #branch-tools { width: 220px; }
#branch-frontend { top: 150px; left: 250px; }
#branch-backend { top: 450px; left: 950px; }
#branch-tools { top: 700px; left: 300px; }
[data-parent] { width: 200px; }
#sub-html { top: 100px; left: -20px; }
#sub-css { top: 230px; left: -50px; }
#sub-js { top: 350px; left: 0px; }
#sub-fw { top: 450px; left: 200px; } /* さらに深い階層 */
#sub-lang { top: 350px; left: 1200px; }
#sub-db { top: 480px; left: 1250px; }
#sub-server { top: 600px; left: 1200px; }
#sub-git { top: 650px; left: 50px; }
#sub-design { top: 780px; left: 0px; }
#sub-build { top: 900px; left: 100px; }
/* --- SVGコネクターのスタイル --- */
.connector-svg { position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; }
.connector-svg path { fill: none; stroke: #556; stroke-width: 3; stroke-dasharray: 0; stroke-dashoffset: 0; transition: stroke-dashoffset 0.8s ease-in-out; }
/* --- 詳細情報スライド(モーダル) --- */
.detail-slide-overlay {
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
display: flex; justify-content: center; align-items: center;
opacity: 0; visibility: hidden; transition: opacity 0.5s ease, visibility 0.5s; z-index: 100;
}
.detail-slide-overlay.visible { opacity: 1; visibility: visible; }
.detail-slide-content {
background: rgba(255, 255, 255, 0.85); backdrop-filter: blur(15px); -webkit-backdrop-filter: blur(15px);
padding: 3rem 4rem; border-radius: 20px; width: 70%; max-width: 800px;
box-shadow: 0 10px 50px rgba(0,0,0,0.2); transform: scale(0.9);
transition: transform 0.5s 0.2s cubic-bezier(0.25, 1, 0.5, 1);
}
.detail-slide-overlay.visible .detail-slide-content { transform: scale(1); }
.detail-slide-content h2 { font-family: 'Yusei Magic', sans-serif; font-size: 2.5rem; margin: 0 0 1.5rem 0; }
.detail-slide-content p { font-size: 1rem; line-height: 2; margin: 0; }
/* --- 閉じる/リセットボタン --- */
.control-btn {
position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%);
font-family: 'Yusei Magic', sans-serif; font-size: 1rem; padding: 10px 25px;
border-radius: 50px; border: 3px solid #334; background-color: #fff; color: #334;
cursor: pointer; box-shadow: 0 4px 10px rgba(0,0,0,0.1); transition: all 0.3s ease;
}
.control-btn:hover { transform: translateY(-3px) translateX(-50%); }
.control-btn.dark-mode { background-color: #334; color: #fff; }
</style>
</head>
<body>
<div class="main-container">
<div class="camera-rig" id="camera-rig">
<div class="presentation-canvas" id="canvas">
<!-- SVGコネクター -->
<svg class="connector-svg">
<path id="line-frontend" d="M 700 500 C 600 500, 400 250, 360 200"></path>
<path id="line-backend" d="M 700 500 C 800 500, 950 500, 1060 500"></path>
<path id="line-tools" d="M 700 500 C 600 600, 450 700, 410 750"></path>
<path id="line-html" d="M 360 200 C 300 200, 150 150, 100 130"></path> <path id="line-css" d="M 360 200 C 300 250, 100 250, 50 260"></path> <path id="line-js" d="M 360 200 C 350 350, 150 350, 100 380"></path>
<path id="line-fw" d="M 100 380 C 150 450, 250 450, 300 480"></path> <!-- さらに深い階層の線 -->
<path id="line-lang" d="M 1060 500 C 1100 450, 1150 400, 1250 380"></path> <path id="line-db" d="M 1060 500 C 1150 500, 1250 500, 1300 510"></path> <path id="line-server" d="M 1060 500 C 1100 550, 1150 600, 1250 630"></path>
<path id="line-git" d="M 410 750 C 350 700, 200 680, 150 680"></path> <path id="line-design" d="M 410 750 C 350 800, 150 800, 100 810"></path> <path id="line-build" d="M 410 750 C 350 850, 200 900, 150 930"></path>
</svg>
<!-- マインドマップノード -->
<div id="central-topic" class="gr-node"><h3>Webサイト制作</h3><p>一枚のWebページが、どのように作られているか見てみましょう。</p></div>
<div id="branch-frontend" class="gr-node" data-branch="frontend"><h3>フロントエンド</h3><p>ユーザーが直接見る、ブラウザ側の世界</p></div>
<div id="branch-backend" class="gr-node" data-branch="backend"><h3>バックエンド</h3><p>目に見えない、サーバー側の世界</p></div>
<div id="branch-tools" class="gr-node" data-branch="tools"><h3>ツールと環境</h3><p>制作を支える様々な道具</p></div>
<div id="sub-html" class="gr-node" data-parent="frontend" data-sub-node="html"><h3>HTML</h3></div>
<div id="sub-css" class="gr-node" data-parent="frontend" data-sub-node="css"><h3>CSS</h3></div>
<div id="sub-js" class="gr-node" data-parent="frontend" data-sub-node="js" data-branch="js"><h3>JavaScript</h3></div> <!-- 展開可能にする -->
<div id="sub-fw" class="gr-node" data-parent="js" data-sub-node="fw"><h3>フレームワーク</h3></div> <!-- さらに深い階層 -->
<div id="sub-lang" class="gr-node" data-parent="backend" data-sub-node="lang"><h3>プログラム言語</h3></div>
<div id="sub-db" class="gr-node" data-parent="backend" data-sub-node="db"><h3>データベース</h3></div>
<div id="sub-server" class="gr-node" data-parent="backend" data-sub-node="server"><h3>サーバー</h3></div>
<div id="sub-git" class="gr-node" data-parent="tools" data-sub-node="git"><h3>Git</h3></div>
<div id="sub-design" class="gr-node" data-parent="tools" data-sub-node="design"><h3>デザインツール</h3></div>
<div id="sub-build" class="gr-node" data-parent="tools" data-sub-node="build"><h3>ビルドツール</h3></div>
</div>
</div>
<div class="detail-slide-overlay" id="detail-slide"></div>
</div>
<button class="control-btn" id="control-btn">リセット</button>
<script>
const cameraRig = document.getElementById('camera-rig');
const canvas = document.getElementById('canvas');
const allNodes = document.querySelectorAll('.gr-node');
const detailSlide = document.getElementById('detail-slide');
const controlButton = document.getElementById('control-btn');
const body = document.body;
const slideData = {
html: { title: 'HTML', detail: 'HyperText Markup Language。Webページの骨格や構造を定義する言語です。全てのテキスト、画像、リンクなどの要素は、このHTMLによって配置されます。建物の基礎や柱に相当します。' },
css: { title: 'CSS', detail: 'Cascading Style Sheets。色、フォント、レイアウトなど、ページの見た目を美しく装飾します。HTMLが骨格なら、CSSはインテリアや塗装の役割を果たします。' },
fw: { title: 'JSフレームワーク', detail: '複雑なアプリケーションを効率的に開発するための骨組みです。React, Vue, Angularなどが有名で、コンポーネントベースの開発を促進します。' },
lang: { title: 'プログラム言語', detail: 'サーバー側で複雑な処理を実行します。ユーザー登録、ログイン認証、データ検索など、リクエストに応じたデータ処理を行います。(例: PHP, Python, Ruby)' },
db: { title: 'データベース', detail: 'ユーザー情報や投稿内容など、大量のデータを効率的に保存・管理する場所です。必要な時に素早くデータを取り出せるよう整理された、巨大な情報の倉庫と言えます。' },
server: { title: 'サーバー', detail: 'Webサイトのファイルやデータベースを保管し、ユーザーのブラウザからのリクエストに応じてデータを提供するコンピューターです。24時間365日稼働し続けます。' },
git: { title: 'Git', detail: 'コードの変更履歴を記録・管理するバージョン管理システム。複数人での共同作業や、問題発生時に過去の状態に安全に戻す際に不可欠なツールです。' },
design: { title: 'デザインツール', detail: 'Webサイトの見た目や使いやすさを設計するためのソフトウェアです。Figma, Adobe XD, Photoshopなどが広く使われ、開発者との連携を円滑にします。' },
build: { title: 'ビルドツール', detail: 'コードの変換やファイルの圧縮・最適化を自動化し、開発効率とサイトのパフォーマンスを向上させます。現代的な開発に欠かせない縁の下の力持ちです。(例: Webpack, Vite)' }
};
const cameraPositions = {
frontend: 'translateX(300px) translateY(200px) scale(0.8)',
backend: 'translateX(-350px) translateY(0px) scale(0.8)',
tools: 'translateX(250px) translateY(-200px) scale(0.8)',
js: 'translateX(450px) translateY(50px) scale(0.7)', // JSフォーカス用
reset: 'translateX(0) translateY(0) scale(1)'
};
const init = () => {
document.querySelectorAll('.connector-svg path').forEach(p => {
p.style.strokeDasharray = p.getTotalLength();
p.style.strokeDashoffset = p.getTotalLength();
});
document.getElementById('central-topic').classList.add('visible');
document.querySelectorAll('[data-branch]').forEach(node => {
node.classList.add('visible');
document.getElementById(`line-${node.dataset.branch}`).style.strokeDashoffset = 0;
});
};
const toggleBranch = (branchName, forceHide = false) => {
const subNodes = document.querySelectorAll(`[data-parent="${branchName}"]`);
const isOpening = !subNodes[0].classList.contains('visible');
const shouldShow = !forceHide && isOpening;
cameraRig.style.transform = shouldShow ? cameraPositions[branchName] : cameraPositions.reset;
if(branchName in cameraPositions) { // 背景はトップレベルのブランチのみ
body.className = shouldShow ? `bg-${branchName}` : '';
controlButton.classList.toggle('dark-mode', body.className !== '' && body.className !== 'bg-frontend');
}
// クリックされたブランチ以外の下位ノードを全て隠す
document.querySelectorAll('.gr-node[data-parent]').forEach(n => {
if (n.dataset.parent !== branchName || !shouldShow) {
n.classList.remove('visible');
}
});
document.querySelectorAll('.connector-svg path[id*="line-"]').forEach(p => {
const isMainLine = ['line-frontend', 'line-backend', 'line-tools'].includes(p.id);
if (!isMainLine) {
p.style.strokeDashoffset = p.getTotalLength();
}
});
if (shouldShow) {
subNodes.forEach(node => {
node.classList.add('visible');
const subNodeName = node.dataset.subNode || node.dataset.branch; // data-sub-nodeまたはdata-branch
const line = document.getElementById(`line-${subNodeName}`);
if(line) line.style.strokeDashoffset = 0;
});
}
};
const showDetailSlide = (subNodeName) => {
const data = slideData[subNodeName];
if (!data) return;
const slideHtml = `
<div class="detail-slide-content">
<h2>${data.title}</h2>
<p>${data.detail}</p>
</div>`;
detailSlide.innerHTML = slideHtml;
detailSlide.classList.add('visible');
canvas.classList.add('focused');
controlButton.textContent = 'マップに戻る';
};
const hideDetailSlide = () => {
detailSlide.classList.remove('visible');
canvas.classList.remove('focused');
controlButton.textContent = 'リセット';
};
allNodes.forEach(node => {
node.addEventListener('click', (e) => {
e.stopPropagation();
const branchName = node.dataset.branch;
const subNodeName = node.dataset.subNode;
if (branchName) { // ブランチノードがクリックされた場合
toggleBranch(branchName);
} else if (subNodeName) { // サブノード(最下位)がクリックされた場合
showDetailSlide(subNodeName);
}
});
});
controlButton.addEventListener('click', () => {
if (detailSlide.classList.contains('visible')) {
hideDetailSlide();
} else {
['frontend', 'backend', 'tools', 'js'].forEach(branch => toggleBranch(branch, true));
cameraRig.style.transform = cameraPositions.reset;
body.className = '';
controlButton.classList.remove('dark-mode');
}
});
init();
</script>
</body>
</html>
Discussion