#javascript #mapbox
#javascript #mapbox
Вопрос:
Я работаю над формой демонстрационного файла MapBox для создания локатора магазина (https://docs.mapbox.com/help/tutorials/building-a-store-locator /)
Я хотел бы добавить панель поиска, которая фильтрует результаты на основе поля «город». Я пытался работать с документацией на веб-сайте MapBox, но безуспешно. https://docs.mapbox.com/mapbox-gl-js/example/filter-features-within-map-view /
HTML / JS
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<title>Store Locator</title>
<meta name='robots' content='noindex, nofollow'>
<meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
<link href='https://fonts.googleapis.com/css?family=Source Sans Pro:400,700' rel='stylesheet'>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.css' rel='stylesheet' />
<link href='stylesheet.css' rel='stylesheet' />
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.12.0/mapbox-gl.js'></script>
<script src='store-info.js'></script>
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.min.js"></script>
<link
rel="stylesheet"
href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.5.1/mapbox-gl-geocoder.css"
type="text/css"
/>
<!-- Promise polyfill script required to use Mapbox GL Geocoder in IE 11 -->
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.min.js"></script>
</head>
<body>
<div class="center-all">
<div class="WTB-container">
<h2>Find a riderwear stockist near you.</h2>
<p>Please contact your chosen store to confirm stock before beginning your journey.</p>
<div class="map-container">
<div class='sidebar'>
<div class='heading'>
<h1>Stores</h1>
</div>
<div id='listings' class='listings'></div>
</div>
<div id='map' class='map'></div>
</div>
</div>
</div>
</body>
</html>
<script>
// This will let you use the .remove() function later on
if (!('remove' in Element.prototype)) {
Element.prototype.remove = function() {
if (this.parentNode) {
this.parentNode.removeChild(this);
}
};
}
mapboxgl.accessToken = 'pk.eyJ1IjoibWFyY3VzdGVzdGFjY291bnQiLCJhIjoiY2tmaTA3ODJ5MHFnZjJxczJla2M3bjRneSJ9.iafUvLt1Zn1Cs8IrRbYhOw';
/**
* Add the map to the page
*/
var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v10',
center: [-1.480048, 53.553637],
zoom: 5,
scrollZoom: true
});
/**
* 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(function(store, i){
store.properties.id = i;
});
/**
* Wait until the map loads to make changes to the map.
*/
map.on('load', function (e) {
/**
* This is where your '.addLayer()' used to be, instead
* add only the source without styling a layer
*/
map.addSource("places", {
"type": "geojson",
"data": stores
});
/**
* Add all the things to the page:
* - The location listings on the side of the page
* - The markers onto the map
*/
buildLocationList(stores);
addMarkers();
});
/**
* Add a marker to the map for every store listing.
**/
function addMarkers() {
/* For each feature in the GeoJSON object above: */
stores.features.forEach(function(marker) {
/* Create a div element for the marker. */
var el = document.createElement('div');
/* Assign a unique `id` to the marker. */
el.id = "marker-" marker.properties.id;
/* Assign the `marker` class to each marker for styling. */
el.className = 'marker';
/**
* Create a marker using the div element
* defined above and add it to the map.
**/
new mapboxgl.Marker(el, { offset: [0, -23] })
.setLngLat(marker.geometry.coordinates)
.addTo(map);
/**
* Listen to the element and when it is clicked, do three things:
* 1. Fly to the point
* 2. Close all other popups and display popup for clicked store
* 3. Highlight listing in sidebar (and remove highlight for all other listings)
**/
el.addEventListener('click', function(e){
/* Fly to the point */
flyToStore(marker);
/* Close all other popups and display popup for clicked store */
createPopUp(marker);
/* Highlight listing in sidebar */
var activeItem = document.getElementsByClassName('active');
e.stopPropagation();
if (activeItem[0]) {
activeItem[0].classList.remove('active');
}
var listing = document.getElementById('listing-' marker.properties.id);
listing.classList.add('active');
});
});
}
/**
* Add a listing for each store to the sidebar.
**/
function buildLocationList(data) {
data.features.forEach(function(store, i){
/**
* Create a shortcut for `store.properties`,
* which will be used several times below.
**/
var prop = store.properties;
/* Add a new listing section to the sidebar. */
var listings = document.getElementById('listings');
var listing = listings.appendChild(document.createElement('div'));
/* Assign a unique `id` to the listing. */
listing.id = "listing-" prop.id;
/* Assign the `item` class to each listing for styling. */
listing.className = 'item';
/* Add the link to the individual listing created above. */
var link = listing.appendChild(document.createElement('a'));
link.href = '#';
link.className = 'title';
link.id = "link-" prop.id;
link.innerHTML = prop.name;
/* Add details to the individual listing. */
var details = listing.appendChild(document.createElement('div'));
details.innerHTML = prop.city;
if (prop.phone) {
details.innerHTML = ' · ' prop.phone;
}
/**
* 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(e){
for (var i=0; i < data.features.length; i ) {
if (this.id === "link-" data.features[i].properties.id) {
var clickedListing = data.features[i];
flyToStore(clickedListing);
createPopUp(clickedListing);
}
}
var 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) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
if (popUps[0]) popUps[0].remove();
var popup = new mapboxgl.Popup({closeOnClick: false})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3>' currentFeature.properties.name '</h3>'
'<h4>' currentFeature.properties.address '</h4>'
'<h4>' currentFeature.properties.county '</h4>'
'<h4>' currentFeature.properties.postalCode '</h4>')
.addTo(map);
}
// Add geolocate control to the map.
map.addControl(
new mapboxgl.GeolocateControl({
positionOptions: {
enableHighAccuracy: true
},
trackUserLocation: true
})
);
// Add zoom and rotation controls to the map.
map.addControl(new mapboxgl.NavigationControl());
CSS
body {
color:#404040;
font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
margin:0;
padding:0;
-webkit-font-smoothing:antialiased;
}
* {
-webkit-box-sizing:border-box;
-moz-box-sizing:border-box;
box-sizing:border-box;
}
h2{
margin-bottom: 0;
}
.center-all{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.WTB-container{
width: 1200px;
height: auto;
margin: auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: left;
}
.map-container{
width: 80%;
height: auto;
display: flex;
justify-content: center;
align-items: center;
margin: 0;
margin-top: 50px;
}
.sidebar {
width:30%;
height:500px;
overflow:hidden;
border-right:1px solid rgba(0,0,0,0.25);
}
.pad2 {
padding:20px;
}
.map {
width:60%;
height: 500px;
}
h1 {
font-size:22px;
margin:0;
font-weight:400;
line-height: 20px;
padding: 20px 2px;
}
a {
color:#404040;
text-decoration:none;
}
a:hover {
color:#101010;
}
.heading {
background:#fff;
border-bottom:1px solid #eee;
min-height:60px;
line-height:60px;
padding:0 10px;
background-color: #1060AB;
color: #fff;
}
.listings {
height:100%;
overflow:auto;
padding-bottom:60px;
}
.listings .item {
display:block;
border-bottom:1px solid #eee;
padding:10px;
text-decoration:none;
}
.listings .item:last-child { border-bottom:none; }
.listings .item .title {
display:block;
color:#1060AB;
font-weight:700;
}
.listings .item .title small { font-weight:400; }
.listings .item.active .title,
.listings .item .title:hover { color:#1060AB; }
.listings .item.active {
background-color:#f8f8f8;
}
::-webkit-scrollbar {
width:3px;
height:3px;
border-left:0;
background:rgba(0,0,0,0.1);
}
::-webkit-scrollbar-track {
background:none;
}
::-webkit-scrollbar-thumb {
background:#1060AB;
border-radius:0;
}
.marker {
border: none;
cursor: pointer;
height: 56px;
width: 56px;
background-image: url(marker.png);
background-color: rgba(0, 0, 0, 0);
}
.clearfix { display:block; }
.clearfix:after {
content:'.';
display:block;
height:0;
clear:both;
visibility:hidden;
}
/* Marker tweaks */
.mapboxgl-popup {
padding-bottom: 50px;
}
.mapboxgl-popup-close-button {
display:none;
}
.mapboxgl-popup-content {
font:400 15px/22px 'Source Sans Pro', 'Helvetica Neue', Sans-serif;
padding:0;
width:180px;
}
.mapboxgl-popup-content-wrapper {
padding:1%;
}
.mapboxgl-popup-content h3 {
background:#1060AB;
color:#fff;
margin:0;
display:block;
padding:10px;
border-radius:3px 3px 0 0;
font-weight:700;
margin-top:-15px;
}
.mapboxgl-popup-content h4 {
margin:0;
display:block;
padding: 10px 10px 10px 10px;
font-weight:400;
}
.mapboxgl-popup-content div {
padding:10px;
}
.mapboxgl-container .leaflet-marker-icon {
cursor:pointer;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-content {
margin-top: 15px;
}
.mapboxgl-popup-anchor-top > .mapboxgl-popup-tip {
border-bottom-color: #1060AB;
}
.mapboxgl-ctrl-compass{
display: none !important;
}
GeoJSON
var stores = {
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.310840,
51.830350
]
},
"properties": {
"name":"Helmet City",
"phone": "01865 372529",
"address": "Saint Georges House, Langford Lane",
"city": "Kidlington",
"county": "Oxfordshire",
"country": "England",
"postalCode": "OX5 1HT",
}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-1.714590,
52.200806
]
},
"properties": {
"name":"Performance Triumph",
"phone": "01789 205149",
"address": "14 Western Road",
"city": "Stratford Upon Avon",
"county": "Warwickshire",
"country": "England",
"postalCode": "CV37 0AH",
}
}
]
};
Nike (https://www.nike.com/gb/retail?latitude=51.50722amp;longitude=-0.1275amp;page=1amp;storesPerPage=15 ) у меня есть функция, которая мне нужна, но я не могу ее воссоздать. Любая помощь будет оценена.
Комментарии:
1. Первое, что нужно понять в mapbox, это то, что вы либо создаете источник и стиль и позволяете ему обрабатывать отображение маркеров, либо создаете маркеры один за другим и забываете об определении источника (здесь вы делаете оба). Кроме того, вы на самом деле не указали, в чем проблема? И последнее, но не менее важное: попробуйте создать скрипку, чтобы вы могли поделиться живым примером