arcgis.ts 2.62 KB
Newer Older
JOE XMG's avatar
update  
JOE XMG committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import * as L from 'leaflet';
import { getJSON } from '../util';
import {
  IGeocoder,
  GeocoderOptions,
  GeocodingCallback,
  geocodingParams,
  GeocodingResult,
  reverseParams
} from './api';

export interface ArcGisOptions extends GeocoderOptions {}

/**
 * Implementation of the [ArcGIS geocoder](https://developers.arcgis.com/features/geocoding/)
 */
export class ArcGis implements IGeocoder {
  options: ArcGisOptions = {
    serviceUrl: 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer',
    apiKey: ''
  };

  constructor(options?: Partial<ArcGisOptions>) {
    L.Util.setOptions(this, options);
  }

  geocode(query: string, cb: GeocodingCallback, context?: any): void {
    const params = geocodingParams(this.options, {
      token: this.options.apiKey,
      SingleLine: query,
      outFields: 'Addr_Type',
      forStorage: false,
      maxLocations: 10,
      f: 'json'
    });

    getJSON(this.options.serviceUrl + '/findAddressCandidates', params, data => {
      const results: GeocodingResult[] = [];
      if (data.candidates && data.candidates.length) {
        for (let i = 0; i <= data.candidates.length - 1; i++) {
          const loc = data.candidates[i];
          const latLng = L.latLng(loc.location.y, loc.location.x);
          const latLngBounds = L.latLngBounds(
            L.latLng(loc.extent.ymax, loc.extent.xmax),
            L.latLng(loc.extent.ymin, loc.extent.xmin)
          );
          results[i] = {
            name: loc.address,
            bbox: latLngBounds,
            center: latLng
          };
        }
      }

      cb.call(context, results);
    });
  }

  suggest(query: string, cb: GeocodingCallback, context?: any): void {
    return this.geocode(query, cb, context);
  }

  reverse(location: L.LatLngLiteral, scale: number, cb: GeocodingCallback, context?: any): void {
    const params = reverseParams(this.options, {
      location: location.lng + ',' + location.lat,
      distance: 100,
      f: 'json'
    });
    getJSON(this.options.serviceUrl + '/reverseGeocode', params, data => {
      const result: GeocodingResult[] = [];
      if (data && !data.error) {
        const center = L.latLng(data.location.y, data.location.x);
        const bbox = L.latLngBounds(center, center);
        result.push({
          name: data.address.Match_addr,
          center: center,
          bbox: bbox
        });
      }

      cb.call(context, result);
    });
  }
}

/**
 * [Class factory method](https://leafletjs.com/reference.html#class-class-factories) for {@link ArcGis}
 * @param options the options
 */
export function arcgis(options?: Partial<ArcGisOptions>) {
  return new ArcGis(options);
}