前回まで
ツーリングアプリの【map編】を終わらせたよ
今回は【絞り込み検索編】です。
ではいきましょう!
ステップ1|ボタンの選択状態を管理しよう
ボタンを押したら見た目が変わるようにしよう
絞り込みボタン(スポットタイプ・季節・難易度)を押したとき、
「選択中」とわかるように見た目を変えます。
まず style.css に選択中のスタイルを追加しましょう。
.select-button.active {
background-color: #25619d;
color: white;
border-color: #25619d;
}
次に script.js でクリックしたボタンに active クラスをつけます。
document.querySelectorAll('.select-button').forEach(btn => {
btn.addEventListener('click', () => {
btn.classList.toggle('active'); // 押すたびにon/offが切り替わる
});
});
- ボタンを押すたびに色が変わることを確認してみましょう
- 次は「選択中のボタンがどれか」を取得する方法を考えます…
ステップ2|選択中の条件を取得しよう
「今どの条件が選ばれているか」を取得する関数を作ろう
検索ボタンを押したとき、active クラスがついているボタンのテキストを集めると
どの条件が選ばれているかがわかります。
function getSelectedValues(groupClass) {
const activeButtons = document.querySelectorAll(`.${groupClass} .select-button.active`);
return Array.from(activeButtons).map(btn => btn.textContent);
}
📌
Array.fromはquerySelectorAllの結果を配列に変換しています
試しにコンソールで確認してみましょう。
document.querySelector('.filter-search').addEventListener('click', () => {
const types = getSelectedValues('type-group');
console.log(types); // ["海", "山"] のように選択中のものが配列で出るはず
});
エリアの選択値も取得しよう
エリアはセレクトボックスなので、取得方法が少し違います。
document.querySelector('.filter-search').addEventListener('click', () => {
const area = document.querySelector('.area-select').value;
console.log(area); // "hokkaido" など value属性の値が取れる
});
ステップ3|スポットデータに条件を追加しよう
spots.js の各データに area / season / level を追加しよう
絞り込みで使う項目がまだデータにないので追加します。
const spots = [
{
name: "稚内 宗谷岬",
area: "hokkaido",
lat: 45.52,
lng: 141.93,
type: "海",
season: "夏",
level: "初心者",
description: "日本最北端の地。地平線まで広がる海が絶景。",
},
{
name: "乗鞍スカイライン",
area: "chubu",
lat: 36.10,
lng: 137.55,
type: "山",
season: "秋",
level: "中級",
description: "標高2700mまで走れる日本屈指の山岳ルート。",
},
// 他のスポットも同様に追加する
];
📌
areaの値はHTMLの<option value="hokkaido">の value と合わせます
ステップ4|条件でスポットを絞り込もう
filterSpots 関数を作ろう
選択中の条件に一致するスポットだけを返す関数を作ります。
条件が何も選ばれていないときは全件そのまま返します。
function filterSpots(area, types, seasons, levels) {
return spots.filter(spot => {
// エリアが選ばれていれば一致するものだけ残す
if (area && spot.area !== area) return false;
// タイプが1つ以上選ばれていれば、どれかに一致するものだけ残す
if (types.length > 0 && !types.includes(spot.type)) return false;
// 季節が1つ以上選ばれていれば、どれかに一致するものだけ残す
if (seasons.length > 0 && !seasons.includes(spot.season)) return false;
// 難易度が1つ以上選ばれていれば、どれかに一致するものだけ残す
if (levels.length > 0 && !levels.includes(spot.level)) return false;
return true; // すべての条件を通過したら残す
});
}
試しにコンソールで確認してみましょう。
document.querySelector('.filter-search').addEventListener('click', () => {
const area = document.querySelector('.area-select').value;
const types = getSelectedValues('type-group');
const seasons = getSelectedValues('season-group');
const levels = getSelectedValues('level-group');
const result = filterSpots(area, types, seasons, levels);
console.log(result); // 絞り込まれたスポットの配列が出るはず
});
ステップ5|絞り込み結果を地図のピンに反映しよう
ピンをあとから消せるように管理しよう
地図のピンは一度立てると消す手段が必要です。
markers という配列に保存しておくことで、まとめて消せるようになります。
まず、ピンを立てているコードを showMarkers 関数にまとめ直しましょう。
let markers = []; // ピンをまとめて管理する配列
function showMarkers(spotsToShow) {
// 今あるピンを全部消す
markers.forEach(marker => marker.setMap(null));
markers = [];
// 渡されたスポットだけピンを立て直す
spotsToShow.forEach(spot => {
const marker = new google.maps.Marker({
position: { lat: spot.lat, lng: spot.lng },
map: map,
title: spot.name,
});
// ホバー・クリックのイベントもここに書く(前のステップのコードを移す)
markers.push(marker); // 配列に追加しておく
});
}
// 最初は全件表示
showMarkers(spots);
検索ボタンを押したら絞り込んでピンを更新しよう
ステップ2〜5をつなぎ合わせます。
document.querySelector('.filter-search').addEventListener('click', () => {
const area = document.querySelector('.area-select').value;
const types = getSelectedValues('type-group');
const seasons = getSelectedValues('season-group');
const levels = getSelectedValues('level-group');
const result = filterSpots(area, types, seasons, levels);
showMarkers(result); // 絞り込み結果でピンを更新
});
- 条件を選んで検索ボタンを押すと、該当するピンだけ地図に残ることを確認しましょう
📌
getSelectedValuesに渡すクラス名は、HTMLの各.filter-groupに
type-group/season-group/level-groupというクラスを追加して区別します
ステップ6|リセットボタンを実装しよう
条件をすべてクリアして全件表示に戻そう
リセットボタンを押したとき、以下の3つをリセットします。
- セレクトボックスを「選択してください」に戻す
-
activeクラスを全ボタンから外す - 全スポットのピンを再表示する
document.querySelector('.filter-reset').addEventListener('click', () => {
// エリアを初期値に戻す
document.querySelector('.area-select').value = '';
// 全ボタンの active を外す
document.querySelectorAll('.select-button').forEach(btn => {
btn.classList.remove('active');
});
// 全スポットを再表示する
showMarkers(spots);
});
- リセットボタンを押したら全件のピンに戻ることを確認してみましょう!
次回
