0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ツーリングスポットアプリ2【絞り込み検索編】

0
Last updated at Posted at 2026-03-24

前回まで

ツーリングアプリの【map編】を終わらせたよ

今回は【絞り込み検索編】です。

下記の赤枠部分を進めていきます
スクリーンショット 2026-04-03 0.00.51.png

ではいきましょう!

ステップ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つをリセットします。

  1. セレクトボックスを「選択してください」に戻す
  2. active クラスを全ボタンから外す
  3. 全スポットのピンを再表示する
document.querySelector('.filter-reset').addEventListener('click', () => {

  // エリアを初期値に戻す
  document.querySelector('.area-select').value = '';

  // 全ボタンの active を外す
  document.querySelectorAll('.select-button').forEach(btn => {
    btn.classList.remove('active');
  });

  // 全スポットを再表示する
  showMarkers(spots);
});
  • リセットボタンを押したら全件のピンに戻ることを確認してみましょう!

次回

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?