1. 企画立案:文化をWebに落とし込む思考法
多くの初心者は「コードを書くこと」に集中しがちですが、最初にすべきは「何を伝えるか」の設計です。地域文化をテーマにする場合、抽象的な「故郷の魅力」ではなく、具体的な要素に絞り込みます。例えば「故郷の城下町の街並み」や「消えゆく手仕事の記録」といった具合です。紙とペン、もしくはマインドマップツールを使って、以下の3点を整理しましょう。
- コアテーマの特定:「古地図と現代の街を重ねるインタラクティブマップ」のように、単一のストーリーに焦点を当てます。
- サイト構造の設計:ホーム、ギャラリー、インタビュー、年表といったセクションを、四角と矢印で図にします。
- ビジュアルコンセプト:地域のイメージカラー(例:沖縄なら青とエメラルドグリーン)や、伝統模様のCSS装飾を検討します。
この段階で「どこにインタラクション(ホバー、クリック、スクロール)を仕掛けるか」を決めておくと、コーディングがスムーズになります。
2. 実践事例1:時を刻む古城壁(シングルページスクロール)
第一弾は、縦スクロールで歴史を追体験するサイトです。CSSのposition: sticky や Intersection Observer API を駆使し、パララックス効果を伴うナラティブを実現します。
<section class="period" id="era-heian">
<div class="bg-layer"></div>
<div class="text-wrap">
<h2>平安時代:城壁の起源</h2>
<p>794年、桓武天皇により…この文章はスクロールに応じてフェードインします。</p>
</div>
</section>
<section class="period" id="era-sengoku">
<!-- 戦国時代のコンテンツ -->
</section>
.period {
height: 100vh;
position: relative;
overflow: hidden;
}
.text-wrap {
opacity: 0;
transform: translateY(40px);
transition: opacity 0.9s ease, transform 0.9s ease;
}
.period.visible .text-wrap {
opacity: 1;
transform: translateY(0);
}
const sections = document.querySelectorAll('.period');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
} else {
entry.target.classList.remove('visible');
}
});
}, { threshold: 0.25 });
sections.forEach(sec => observer.observe(sec));
ポイントは、各セクションの背景画像に統一感を持たせつつ、文章の出現タイミングを微調整することです。何度もスクロールしながら、最も自然に見える閾値を探りましょう。
3. 実践事例2:郷土料理マップ(SVG+モーダル)
次は、地図上の地域をクリックすると、その土地の名物料理がポップアップで表示されるインタラクティブマップです。SVGのパス要素とモーダルウィンドウを組み合わせます。
<svg viewBox="0 0 600 450" class="local-map">
<path id="zone-north" d="M 50 50 L 150 50 L 120 150 Z" fill="#d4c8b0" stroke="#5a4a3a"/>
<path id="zone-south" d="M 200 200 C 250 150 350 180 300 280 Z" fill="#b0c4d4"/>
</svg>
<div id="dish-modal" class="modal hidden">
<div class="modal-inner">
<h3 class="dish-name"></h3>
<img class="dish-img" src="" alt="">
<p class="dish-desc"></p>
<button class="close-modal">✕</button>
</div>
</div>
const dishData = {
'zone-north': {
name: '北部の山菜そば',
img: 'img/soba.jpg',
desc: '地元で採れた山菜を使った、香り高い一杯。'
},
'zone-south': {
name: '南部の海鮮丼',
img: 'img/donburi.jpg',
desc: '新鮮な魚介をたっぷり乗せた、漁師町の味。'
}
};
document.querySelectorAll('.local-map path').forEach(area => {
area.addEventListener('click', function() {
const id = this.id;
const data = dishData[id];
if (data) {
document.querySelector('.dish-name').textContent = data.name;
document.querySelector('.dish-img').src = data.img;
document.querySelector('.dish-desc').textContent = data.desc;
document.getElementById('dish-modal').classList.remove('hidden');
}
});
});
document.querySelector('.close-modal').addEventListener('click', () => {
document.getElementById('dish-modal').classList.add('hidden');
});
SVGの各領域にはユニークなIDを付与し、JavaScriptのデータオブジェクトで食材情報と紐付けます。クリックでモーダルを表示する際、classList.toggle を使えば開閉もスムーズです。