Files
2026-05-15 18:33:51 +02:00

374 lines
12 KiB
JavaScript

/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Other/javascript.js to edit this template
*/
mapboxgl.accessToken = 'pk.eyJ1IjoiZXhhbXBsZXMiLCJhIjoiY2p0MG01MXRqMW45cjQzb2R6b2ptc3J4MSJ9.zA2W0IkI0c6KaAhJfk9bWg';
/**
* Add the map to the page
*/
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-77.034084142948, 38.909671288923],
zoom: 13,
scrollZoom: false
});
const stores = {
'type': 'FeatureCollection',
'features': [
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.034084142948, 38.909671288923]
},
'properties': {
'phoneFormatted': '(202) 234-7336',
'phone': '2022347336',
'address': '1471 P St NW',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'at 15th St NW',
'postalCode': '20005',
'state': 'D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.049766, 38.900772]
},
'properties': {
'phoneFormatted': '(202) 507-8357',
'phone': '2025078357',
'address': '2221 I St NW',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'at 22nd St NW',
'postalCode': '20037',
'state': 'D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.043929, 38.910525]
},
'properties': {
'phoneFormatted': '(202) 387-9338',
'phone': '2023879338',
'address': '1512 Connecticut Ave NW',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'at Dupont Circle',
'postalCode': '20036',
'state': 'D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.0672, 38.90516896]
},
'properties': {
'phoneFormatted': '(202) 337-9338',
'phone': '2023379338',
'address': '3333 M St NW',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'at 34th St NW',
'postalCode': '20007',
'state': 'D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.002583742142, 38.887041080933]
},
'properties': {
'phoneFormatted': '(202) 547-9338',
'phone': '2025479338',
'address': '221 Pennsylvania Ave SE',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'btwn 2nd & 3rd Sts. SE',
'postalCode': '20003',
'state': 'D.C.'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-76.933492720127, 38.99225245786]
},
'properties': {
'address': '8204 Baltimore Ave',
'city': 'College Park',
'country': 'United States',
'postalCode': '20740',
'state': 'MD'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.097083330154, 38.980979]
},
'properties': {
'phoneFormatted': '(301) 654-7336',
'phone': '3016547336',
'address': '4831 Bethesda Ave',
'cc': 'US',
'city': 'Bethesda',
'country': 'United States',
'postalCode': '20814',
'state': 'MD'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.359425054188, 38.958058116661]
},
'properties': {
'phoneFormatted': '(571) 203-0082',
'phone': '5712030082',
'address': '11935 Democracy Dr',
'city': 'Reston',
'country': 'United States',
'crossStreet': 'btw Explorer & Library',
'postalCode': '20190',
'state': 'VA'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.10853099823, 38.880100922392]
},
'properties': {
'phoneFormatted': '(703) 522-2016',
'phone': '7035222016',
'address': '4075 Wilson Blvd',
'city': 'Arlington',
'country': 'United States',
'crossStreet': 'at N Randolph St.',
'postalCode': '22203',
'state': 'VA'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-75.28784, 40.008008]
},
'properties': {
'phoneFormatted': '(610) 642-9400',
'phone': '6106429400',
'address': '68 Coulter Ave',
'city': 'Ardmore',
'country': 'United States',
'postalCode': '19003',
'state': 'PA'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-75.20121216774, 39.954030175164]
},
'properties': {
'phoneFormatted': '(215) 386-1365',
'phone': '2153861365',
'address': '3925 Walnut St',
'city': 'Philadelphia',
'country': 'United States',
'postalCode': '19104',
'state': 'PA'
}
},
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [-77.043959498405, 38.903883387232]
},
'properties': {
'phoneFormatted': '(202) 331-3355',
'phone': '2023313355',
'address': '1901 L St. NW',
'city': 'Washington DC',
'country': 'United States',
'crossStreet': 'at 19th St',
'postalCode': '20036',
'state': 'D.C.'
}
}
]
};
/**
* Assign a unique id to each store. You'll use this `id`
* later to associate each point on the map with a listing
* in the sidebar.
*/
stores.features.forEach((store, i) => {
store.properties.id = i;
});
/**
* Wait until the map loads to make changes to the map.
*/
map.on('load', () => {
/* Add the data to your map as a layer */
map.addLayer({
'id': 'locations',
'type': 'circle',
/* Add a GeoJSON source containing place coordinates and information. */
'source': {
'type': 'geojson',
'data': stores
}
});
/**
* Add things to the page:
* - The location listings on the side of the page
*/
buildLocationList(stores);
});
/**
* Listen to the map and when it is clicked, do three things:
* 1. Query the map to determine if a feature in the
* "locations" layer exists at that point.
* 2. If yes, then:
* a. Fly to the point
* b. Close all other popups and display popup for clicked store
* c. Highlight listing in sidebar (and remove highlight for all other listings)
**/
map.on('click', (event) => {
/* Query the map to determine if a feature in the "locations" layer exists at that point. */
const features = map.queryRenderedFeatures(event.point, {
layers: ['locations']
});
/* If it does not exist, return */
if (!features.length) return;
const clickedPoint = features[0];
/* Fly to the point */
flyToStore(clickedPoint);
/* Close all other popups and display popup for clicked store */
createPopUp(clickedPoint);
/* Highlight listing in sidebar (and remove highlight for all other listings) */
const activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
const listing = document.getElementById(
`listing-${clickedPoint.properties.id}`
);
listing.classList.add('active');
});
/**
* Add a listing for each store to the sidebar.
**/
function buildLocationList(stores) {
for (const store of stores.features) {
/* Add a new listing section to the sidebar. */
const listings = document.getElementById('listings');
const listing = listings.appendChild(document.createElement('div'));
/* Assign a unique `id` to the listing. */
listing.id = `listing-${store.properties.id}`;
/* Assign the `item` class to each listing for styling. */
listing.className = 'item';
/* Add the link to the individual listing created above. */
const link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.id = `link-${store.properties.id}`;
link.innerHTML = `${store.properties.address}`;
/* Add details to the individual listing. */
const details = listing.appendChild(document.createElement('div'));
details.innerHTML = `${store.properties.city}`;
if (store.properties.phone) {
details.innerHTML += ` · ${store.properties.phoneFormatted}`;
}
if (store.properties.distance) {
const roundedDistance =
Math.round(store.properties.distance * 100) / 100;
details.innerHTML += `<div><strong>${roundedDistance} miles away</strong></div>`;
}
/**
* Listen to the element and when it is clicked, do four things:
* 1. Update the `currentFeature` to the store associated with the clicked link
* 2. Fly to the point
* 3. Close all other popups and display popup for clicked store
* 4. Highlight listing in sidebar (and remove highlight for all other listings)
**/
link.addEventListener('click', function () {
for (const feature of stores.features) {
if (this.id === `link-${feature.properties.id}`) {
flyToStore(feature);
createPopUp(feature);
}
}
const activeItem = document.getElementsByClassName('active');
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
this.parentNode.classList.add('active');
});
}
}
/**
* Use Mapbox GL JS's `flyTo` to move the camera smoothly
* a given center point.
**/
function flyToStore(currentFeature) {
map.flyTo({
center: currentFeature.geometry.coordinates,
zoom: 15
});
}
/**
* Create a Mapbox GL JS `Popup`.
**/
function createPopUp(currentFeature) {
const popUps = document.getElementsByClassName('mapboxgl-popup');
if (popUps[0]) popUps[0].remove();
const popup = new mapboxgl.Popup({ closeOnClick: false })
.setLngLat(currentFeature.geometry.coordinates)
.setHTML(
`<h3>Sweetgreen</h3><h4>${currentFeature.properties.address}</h4>`
)
.addTo(map);
}