Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

typescript - Mapbox using localGeocoderOnly: true doesn't work without it works

I have an Mapbox GL JS App with a Geocoder. Here I have a localGeocoder which works fine when I don't have the Option "localGeocoderOnly" set on true. Sadly this is a requirement and I only want to use my local Geocoder.

I logged the matchingFeature with the Option on true and default. Both outputs the same object with arrays.

Without "localGeocoderOnly: true"

With "localGeocoderOnly: true"

Im using v4.5.1 geocoder and mapbox v2.0.1.

How I add the geocoder:

    private createGeoCoder(): void {
        const geocoder = new MapboxGeocoder({
          accessToken: mapboxgl.accessToken,
          localGeocoderOnly: true,
          localGeocoder: this.localSearch,
          mapboxgl: this.map
        });
        this.map.addControl(geocoder, 'top-right');
      }

Edit for additional information:

It is a Angular project the implementation of the geocoder looks as following.

public createGeoCoder(): void {
    const geocoder = new MapboxGeocoder({
      accessToken: mapboxgl.accessToken,
      // localGeocoderOnly: true,
      localGeocoder: this.localSearch,
      mapboxgl: this.map
    });
    this.map.addControl(geocoder, 'top-right');
  }

  public localSearch(query): any {
    const matchingFeatures = [];
    fetch('/assets/geoData/20201027-LI-Datenerfassung_Layer_def.json')
      .then(res => res.json())
      .then((data) => {
          data.features.forEach(feature => {
              if (
                feature.properties.title
                  .toLowerCase()
                  .search(query.toLowerCase()) !== -1
              ) {
                feature['place_name'] = '?? ' + feature.properties.title;
                feature['center'] = feature.geometry.coordinates;
                feature['adress'] = feature.properties.adress;
                matchingFeatures.push(feature);
              }
          });
        }
      );
    console.log(matchingFeatures);
    return matchingFeatures;
  }
question from:https://stackoverflow.com/questions/65626370/mapbox-using-localgeocoderonly-true-doesnt-work-without-it-works

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I added localGeocoderOnly: true, to this sample and it looks it works.

Maybe other part affects the result. Could you provide more information about your implementation?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Supplement forward geocoding search results from another data source</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v2.0.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v2.0.1/mapbox-gl.css" rel="stylesheet" />
<style>
    body { margin: 0; padding: 0; }
    #map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<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>
<div id="map"></div>

<script>
    mapboxgl.accessToken = 'pk.eyJ1IjoieW9jaGkiLCJhIjoiY2tjZThvdWExMDV2dDJxcDgxZzBwbzlxYSJ9.M0yRA6SXDMRgXzXGuYnvsg';
    var map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/streets-v11',
        center: [-87.6244, 41.8756],
        zoom: 13
    });

    var customData = {
        'features': [
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Lincoln Park',
                    'description':
                        'A northside park that is home to the Lincoln Park Zoo'
                },
                'geometry': {
                    'coordinates': [-87.637596, 41.940403],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Burnham Park',
                    'description': "A lakefront park on Chicago's south side"
                },
                'geometry': {
                    'coordinates': [-87.603735, 41.829985],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Millennium Park',
                    'description':
                        'A downtown park known for its art installations and unique architecture'
                },
                'geometry': {
                    'coordinates': [-87.622554, 41.882534],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Grant Park',
                    'description':
                        "A downtown park that is the site of many of Chicago's favorite festivals and events"
                },
                'geometry': {
                    'coordinates': [-87.619185, 41.876367],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Humboldt Park',
                    'description': "A large park on Chicago's northwest side"
                },
                'geometry': {
                    'coordinates': [-87.70199, 41.905423],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Douglas Park',
                    'description':
                        "A large park near in Chicago's North Lawndale neighborhood"
                },
                'geometry': {
                    'coordinates': [-87.699329, 41.860092],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Calumet Park',
                    'description':
                        'A park on the Illinois-Indiana border featuring a historic fieldhouse'
                },
                'geometry': {
                    'coordinates': [-87.530221, 41.715515],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Jackson Park',
                    'description':
                        "A lakeside park that was the site of the 1893 World's Fair"
                },
                'geometry': {
                    'coordinates': [-87.580389, 41.783185],
                    'type': 'Point'
                }
            },
            {
                'type': 'Feature',
                'properties': {
                    'title': 'Columbus Park',
                    'description':
                        "A large park in Chicago's Austin neighborhood"
                },
                'geometry': {
                    'coordinates': [-87.769775, 41.873683],
                    'type': 'Point'
                }
            }
        ],
        'type': 'FeatureCollection'
    };

    function forwardGeocoder(query) {
        var matchingFeatures = [];
        for (var i = 0; i < customData.features.length; i++) {
            var feature = customData.features[i];
            // handle queries with different capitalization than the source data by calling toLowerCase()
            if (
                feature.properties.title
                    .toLowerCase()
                    .search(query.toLowerCase()) !== -1
            ) {
                // add a tree emoji as a prefix for custom data results
                // using carmen geojson format: https://github.com/mapbox/carmen/blob/master/carmen-geojson.md
                feature['place_name'] = '?? ' + feature.properties.title;
                feature['center'] = feature.geometry.coordinates;
                feature['place_type'] = ['park'];
                matchingFeatures.push(feature);
            }
        }
        return matchingFeatures;
    }

    map.addControl(
        new MapboxGeocoder({
            accessToken: mapboxgl.accessToken,
            localGeocoder: forwardGeocoder,
            localGeocoderOnly: true,
            zoom: 14,
            placeholder: 'Enter search e.g. Lincoln Park',
            mapboxgl: mapboxgl
        })
    );

enter image description here

Additional information:

localGeocoder does not support Promise. i.e. it expects your function returns the result immediately.

To support Promise based custom geocoder, externalGeocoder was implemented in this PR and planed to release v4.6.1. Unfortunately, v4.6.1 was canceled and v4.7.0 is not yet prepared.

If you want to use externalGeocoder, building the library is the fastest.

Once you prepare the library, following code would work.

    map.addControl(
        new MapboxGeocoder({
            accessToken: mapboxgl.accessToken,
            localGeocoder: dummy,
            localGeocoderOnly: true,
            externalGeocoder : localSearch,
            zoom: 14,
            placeholder: 'Enter search e.g. Lincoln Park',
            mapboxgl: mapboxgl
        })
    );

    function dummy() {
        console.log('dummy');
        return [];
    }

    function localSearch(query) {
      const matchingFeatures = [];
      return fetch('data.json')
        .then(res => res.json())
        .then((data) => {
            console.log(data);
            data.features.forEach(feature => {
                if (
                  feature.properties.title
                    .toLowerCase()
                    .search(query.toLowerCase()) !== -1
                ) {
                  feature['place_name'] = '?? ' + feature.properties.title;
                  feature['center'] = feature.geometry.coordinates;
                  feature['adress'] = feature.properties.adress;
                  matchingFeatures.push(feature);
                }
            });

            return Promise.resolve(matchingFeatures);
          }
        );
    }

Please note that

  1. you need to set localGeocoderOnly. This flag is used to exclude Mapbox Geocoding access here.
  2. you need to set dummy localGeocoder function because this code checks the existence of the function.
  3. then this code calls external geocoder which expects Promise as a return value.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...