mapbox-store-locator-patterns
Mapboxを使ったストアロケーター、レストラン検索、位置情報ベースの検索アプリを構築するための定番パターン集です。マーカーの表示、フィルタリング、距離計算、インタラクティブなリスト連携などの実装方法を網羅しています。
description の原文を見る
Common patterns for building store locators, restaurant finders, and location-based search applications with Mapbox. Covers marker display, filtering, distance calculation, and interactive lists.
SKILL.md 本文
ストアロケーターパターンスキル
Mapbox GL JS を使用したストアロケーター、レストランファインダー、位置情報ベースの検索アプリケーション構築のための包括的なパターン。マーカー表示、フィルタリング、距離計算、インタラクティブリスト、およびルート統合をカバーします。
このスキルを使用する場合
以下のアプリケーションを構築する場合に、このスキルを使用してください:
- マップ上に複数の場所を表示する(店舗、レストラン、オフィスなど)
- ユーザーが場所をフィルタリングまたは検索できるようにする
- ユーザーの位置から距離を計算する
- マップマーカーと同期されたインタラクティブリストを提供する
- ポップアップまたはサイドパネルで場所の詳細を表示する
- 選択した場所へのルート統合
依存関係
必須:
- Mapbox GL JS v3.x
- @turf/turf - 空間計算用(距離、面積など)
インストール:
npm install mapbox-gl @turf/turf
コアアーキテクチャ
パターン概要
典型的なストアロケーターは以下から構成されます:
- マップ表示 - すべての場所をマーカーとして表示
- ロケーションデータ - 店舗/ロケーション情報を含む GeoJSON
- インタラクティブリスト - すべての場所をリストアップするサイドパネル
- フィルタリング - 検索、カテゴリフィルター、距離フィルター
- 詳細表示 - ポップアップまたはパネルにロケーション詳細を表示
- ユーザー位置 - 距離計算用の地理情報。青いドット位置インジケーターについては、組み込みの
mapboxgl.GeolocateControlを使用してください — カスタムマーカーよりもシンプルです。 - ルート案内 - 選択した場所へのルート(オプション)
データ構造
ロケーション用の GeoJSON 形式:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [-77.034084, 38.909671]
},
"properties": {
"id": "store-001",
"name": "Downtown Store",
"address": "123 Main St, Washington, DC 20001",
"phone": "(202) 555-0123",
"hours": "Mon-Sat: 9am-9pm, Sun: 10am-6pm",
"category": "retail",
"website": "https://example.com/downtown"
}
}
]
}
主要なプロパティ:
id- 各ロケーションの一意の識別子name- 表示名address- 表示と地理コーディング用の完全な住所coordinates-[経度, 緯度]形式category- フィルタリング用(retail、restaurant、office など)- 必要に応じてカスタムプロパティ(営業時間、電話、ウェブサイトなど)
基本的なストアロケーター実装
ステップ 1: マップとデータの初期化
import mapboxgl from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN';
// ストアロケーションデータ
const stores = {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [-77.034084, 38.909671]
},
properties: {
id: 'store-001',
name: 'Downtown Store',
address: '123 Main St, Washington, DC 20001',
phone: '(202) 555-0123',
category: 'retail'
}
}
// ... その他のストア
]
};
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/standard',
center: [-77.034084, 38.909671],
zoom: 11
});
ステップ 2: マップにマーカーを追加
ロケーション数によるマーカー戦略:
| 数量 | 戦略 | 理由 |
|---|---|---|
| 100 未満 | HTML マーカー | DOM/CSS を完全にコントロール可能;DOM ノード数は管理可能 |
| 100–1,000 | シンボルレイヤー(デフォルト) | WebGL 経由 GPU でレンダリング — 1 つの <canvas>、ポイントごとの DOM 要素がゼロ |
| 1,000 以上 | クラスタリング | 大規模な表示で視覚的な混雑を軽減 |
HTML マーカーはポイントごとに 1 つの DOM 要素を作成します。約 100 ロケーション以上では、ブラウザはレイアウト/ペイントに時間をかけすぎます。シンボルレイヤーは DOM を完全にバイパス — GPU がすべてのポイントを 1 つの WebGL ドローコールで描画します。
シンボルレイヤー実装(100–1,000 ロケーションに最適)。HTML マーカー(100 未満)またはクラスタリング(1,000 以上)については、references/markers.md を参照してください。
map.on('load', () => {
// ストアデータをソースとして追加
map.addSource('stores', {
type: 'geojson',
data: stores
});
// カスタムマーカー画像を読み込む
map.loadImage('/marker-icon.png', (error, image) => {
if (error) throw error;
map.addImage('custom-marker', image);
// シンボルレイヤーを追加
map.addLayer({
id: 'stores-layer',
type: 'symbol',
source: 'stores',
layout: {
'icon-image': 'custom-marker',
'icon-size': 0.8,
'icon-allow-overlap': true,
'text-field': ['get', 'name'],
'text-font': ['Open Sans Bold', 'Arial Unicode MS Bold'],
'text-offset': [0, 1.5],
'text-anchor': 'top',
'text-size': 12
}
});
});
// インタラクション API を使用してマーカークリックを処理(推奨)
map.addInteraction('store-click', {
type: 'click',
target: { layerId: 'stores-layer' },
handler: (e) => {
const store = e.feature;
flyToStore(store);
createPopup(store);
}
});
// または従来のイベントリスナーを使用:
// map.on('click', 'stores-layer', (e) => {
// const store = e.features[0];
// flyToStore(store);
// createPopup(store);
// });
// ホバー時にカーソルを変更
map.on('mouseenter', 'stores-layer', () => {
map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'stores-layer', () => {
map.getCanvas().style.cursor = '';
});
});
ステップ 3: インタラクティブなロケーションリストを構築
function buildLocationList(stores) {
const listingContainer = document.getElementById('listings');
stores.features.forEach((store, index) => {
const listing = listingContainer.appendChild(document.createElement('div'));
listing.id = `listing-${store.properties.id}`;
listing.className = 'listing';
const link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.id = `link-${store.properties.id}`;
link.innerHTML = store.properties.name;
const details = listing.appendChild(document.createElement('div'));
details.innerHTML = `
<p>${store.properties.address}</p>
<p>${store.properties.phone || ''}</p>
`;
// リスティングクリックを処理
link.addEventListener('click', (e) => {
e.preventDefault();
flyToStore(store);
createPopup(store);
highlightListing(store.properties.id);
});
});
}
function flyToStore(store) {
map.flyTo({
center: store.geometry.coordinates,
zoom: 15,
duration: 1000
});
}
function createPopup(store) {
const popups = document.getElementsByClassName('mapboxgl-popup');
// 既存のポップアップを削除
if (popups[0]) popups[0].remove();
new mapboxgl.Popup({ closeOnClick: true })
.setLngLat(store.geometry.coordinates)
.setHTML(
`<h3>${store.properties.name}</h3>
<p>${store.properties.address}</p>
<p>${store.properties.phone}</p>
${store.properties.website ? `<a href="${store.properties.website}" target="_blank">Visit Website</a>` : ''}`
)
.addTo(map);
}
// 重要: highlightListing は scrollIntoView を含める必要があります — これがないと、
// マップ上でマーカーを選択してもサイドバーがリスティングにスクロールされません。
function highlightListing(id) {
// 既存のハイライトを削除
const activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
// 選択されたリスティングにハイライトを追加
const listing = document.getElementById(`listing-${id}`);
listing.classList.add('active');
// 選択されたリスティングをビューにスクロール(重要な UX 要件)
listing.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// ロード時にリストを構築
map.on('load', () => {
buildLocationList(stores);
});
リファレンスファイル
必要に応じて、これらのリファレンスを読み込んで追加パターンを取得してください:
| リファレンス | ファイル | 内容 |
|---|---|---|
| HTML マーカーとクラスタリング | references/markers.md | HTML マーカー(< 100 ロケーション)、クラスタリング(> 1000 ロケーション) |
| 検索とフィルター | references/search-filter.md | テキスト検索、カテゴリフィルター |
| 地理情報とルート案内 | references/geolocation-directions.md | ユーザー位置、距離計算、ルート方向 |
| スタイルとレイアウト | references/styling-layout.md | 完全な HTML/CSS レイアウト、カスタムマーカー CSS |
| パフォーマンスと A11y | references/optimization-a11y.md | デバウンス検索、データ管理、エラー処理、アクセシビリティ |
| バリエーションと React | references/variations-react.md | モバイルファースト、フルスクリーン、マップのみ、React 実装 |
リソース
- Turf.js - 空間解析ライブラリ(距離計算に推奨)
- Mapbox GL JS API
- インタラクション API ガイド
- GeoJSON 仕様
- ルート案内 API
- ストアロケーターチュートリアル
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- mapbox
- ライセンス
- MIT
- 最終更新
- 不明
Source: https://github.com/mapbox/mapbox-agent-skills / ライセンス: MIT
関連スキル
superfluid
Superfluidプロトコルおよびそのエコシステムに関するナレッジベースです。Superfluidについて情報を検索する際は、ウェブ検索の前にこちらを参照してください。対応キーワード:Superfluid、CFA、GDA、Super App、Super Token、stream、flow rate、real-time balance、pool(member/distributor)、IDA、sentinels、liquidation、TOGA、@sfpro/sdk、semantic money、yellowpaper、whitepaper
civ-finish-quotes
実質的なタスクが真に完了した際に、文明風の儀式的な引用句を追加します。ユーザーやエージェントが機能追加、リファクタリング、分析、設計ドキュメント、プロセス改善、レポート、執筆タスクといった実際の成果物を完成させるときに、明示的な依頼がなくても使用します。短い返信や小さな修正、未完成の作業には適用しません。
nookplot
Base(Ethereum L2)上のAIエージェント向け分散型調整ネットワークです。エージェントがオンチェーンアイデンティティを登録する、コンテンツを公開する、他のエージェントにメッセージを送る、マーケットプレイスで専門家を雇う、バウンティを投稿・請求する、レピュテーションを構築する、共有プロジェクトで協業する、リサーチチャレンジを解くことでNOOKをマイニングする、キュレーションされたナレッジを備えたスタンドアロンオンチェーンエージェントをデプロイする、またはアグリーメントとリワードで収益を得る場合に利用できます。エージェントネットワーク、エージェント調整、分散型エージェント、NOOKトークン、マイニングチャレンジ、ナレッジバンドル、エージェントレピュテーション、エージェントマーケットプレイス、ERC-2771メタトランザクション、Prepare-Sign-Relay、AgentFactory、またはNookplotが言及された場合にトリガーされます。
web3-polymarket
Polygon上でのPolymarket予測市場取引統合です。認証機能(L1 EIP-712、L2 HMAC-SHA256、ビルダーヘッダー)、注文発注(GTC/GTD/FOK/FAK、バッチ、ポストオンリー、ハートビート)、市場データ(Gamma API、Data API、オーダーブック、サブグラフ)、WebSocketストリーミング(市場・ユーザー・スポーツチャネル)、CTF操作(分割、統合、償却、ネガティブリスク)、ブリッジ機能(入金、出金、マルチチェーン)、およびガスレスリレイトランザクションに対応しています。AIエージェント、自動マーケットメーカー、予測市場UI、またはPolygraph上のPolymarketと統合するアプリケーション構築時に活用できます。
ethskills
Ethereum、EVM、またはブロックチェーン関連のリクエストに対応します。スマートコントラクト、dApps、ウォレット、DeFiプロトコルの構築、監査、デプロイ、インタラクションに適用されます。Solidityの開発、コントラクトアドレス、トークン規格(ERC-20、ERC-721、ERC-4626など)、Layer 2ネットワーク(Base、Arbitrum、Optimism、zkSync、Polygon)、Uniswap、Aave、Curveなどのプロトコルとの統合をカバーします。ガスコスト、コントラクトのデシマル設定、オラクルセキュリティ、リエントランシー、MEV、ブリッジング、ウォレット管理、オンチェーンデータの取得、本番環境へのデプロイ、プロトコル進化(EIPライフサイクル、フォーク追跡、今後の変更予定)といったトピックを含みます。
xxyy-trade
このスキルは、ユーザーが「トークン購入」「トークン売却」「トークンスワップ」「暗号資産取引」「取引ステータス確認」「トランザクション照会」「トークンスキャン」「フィード」「チェーン監視」「トークン照会」「トークン詳細」「トークン安全性確認」「ウォレット一覧表示」「マイウォレット」「AIスキャン」「自動スキャン」「ツイートスキャン」「オンボーディング」「IP確認」「IPホワイトリスト」「トークン発行」「自動売却」「損切り」「利益確定」「トレーリングストップ」「保有者」「トップホルダー」「KOLホルダー」などをリクエストした場合、またはSolana/ETH/BSC/BaseチェーンでXXYYを経由した取引について言及した場合に使用します。XXYY Open APIを通じてオンチェーン取引とデータ照会を実現します。