Repository: visgl/react-map-gl Branch: master Commit: c41e00c2d815 Files: 586 Total size: 2.2 MB Directory structure: gitextract_r_hkj0e0/ ├── .eslintignore ├── .eslintrc.cjs ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug-report.yml │ │ ├── config.yml │ │ └── feature-request.yml │ ├── SECURITY.md │ └── workflows/ │ ├── release.yml │ ├── test.yml │ └── website.yml ├── .gitignore ├── .nvmrc ├── .ocularrc.js ├── .prettierrc ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── TESTING.md ├── docs/ │ ├── .gitignore │ ├── README.md │ ├── api-reference/ │ │ ├── mapbox/ │ │ │ ├── attribution-control.md │ │ │ ├── fullscreen-control.md │ │ │ ├── geolocate-control.md │ │ │ ├── layer.md │ │ │ ├── map-provider.md │ │ │ ├── map.md │ │ │ ├── marker.md │ │ │ ├── navigation-control.md │ │ │ ├── popup.md │ │ │ ├── scale-control.md │ │ │ ├── source.md │ │ │ ├── types.md │ │ │ ├── use-control.md │ │ │ └── use-map.md │ │ └── maplibre/ │ │ ├── attribution-control.md │ │ ├── fullscreen-control.md │ │ ├── geolocate-control.md │ │ ├── globe-control.md │ │ ├── layer.md │ │ ├── logo-control.md │ │ ├── map-provider.md │ │ ├── map.md │ │ ├── marker.md │ │ ├── navigation-control.md │ │ ├── popup.md │ │ ├── scale-control.md │ │ ├── source.md │ │ ├── terrain-control.md │ │ ├── types.md │ │ ├── use-control.md │ │ └── use-map.md │ ├── get-started/ │ │ ├── adding-custom-data.md │ │ ├── get-started.md │ │ ├── mapbox-tokens.md │ │ ├── state-management.md │ │ └── tips-and-tricks.md │ ├── table-of-contents.json │ ├── upgrade-guide.md │ └── whats-new.md ├── examples/ │ ├── .data/ │ │ ├── bart-station.json │ │ ├── cities.json │ │ ├── feature-example-sf.json │ │ ├── us-election-2016.json │ │ └── us-income.geojson │ ├── .eslintrc │ ├── get-started/ │ │ ├── basic/ │ │ │ ├── README.md │ │ │ ├── app.jsx │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ └── vite.config.js │ │ ├── controlled/ │ │ │ ├── README.md │ │ │ ├── app.jsx │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ └── vite.config.js │ │ ├── hook/ │ │ │ ├── README.md │ │ │ ├── app.jsx │ │ │ ├── controls.jsx │ │ │ ├── controls2.jsx │ │ │ ├── index.html │ │ │ ├── map.jsx │ │ │ ├── package.json │ │ │ └── vite.config.js │ │ ├── maplibre/ │ │ │ ├── README.md │ │ │ ├── app.jsx │ │ │ ├── index.html │ │ │ └── package.json │ │ ├── nextjs/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── next.config.js │ │ │ ├── package.json │ │ │ └── pages/ │ │ │ ├── _app.js │ │ │ └── index.js │ │ └── redux/ │ │ ├── README.md │ │ ├── app.jsx │ │ ├── controls.jsx │ │ ├── index.html │ │ ├── map.jsx │ │ ├── package.json │ │ ├── store.js │ │ └── vite.config.js │ ├── mapbox/ │ │ ├── clusters/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── layers.ts │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── controls/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── pin.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── custom-cursor/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── custom-overlay/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── custom-overlay.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── deckgl-overlay/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ └── app.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── draggable-markers/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── pin.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── draw-polygon/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── draw-control.ts │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── filter/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── map-style.ts │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── geocoder/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── geocoder-control.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── geojson/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ ├── map-style.ts │ │ │ │ └── utils.ts │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── geojson-animation/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── heatmap/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── map-style.ts │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── interaction/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── layers/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── map-style-basic-v8.json │ │ ├── side-by-side/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── terrain/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ ├── viewport-animation/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ ├── tsconfig.json │ │ │ └── vite.config.js │ │ └── zoom-to-bounds/ │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── maplibre/ │ │ ├── clusters/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── layers.ts │ │ │ └── tsconfig.json │ │ ├── controls/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── pin.tsx │ │ │ └── tsconfig.json │ │ ├── custom-cursor/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── custom-overlay/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── custom-overlay.tsx │ │ │ └── tsconfig.json │ │ ├── deckgl-overlay/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ └── app.tsx │ │ │ └── tsconfig.json │ │ ├── draggable-markers/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── pin.tsx │ │ │ └── tsconfig.json │ │ ├── draw-polygon/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── draw-control.ts │ │ │ └── tsconfig.json │ │ ├── filter/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── map-style.ts │ │ │ └── tsconfig.json │ │ ├── geocoder/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── geocoder-control.tsx │ │ │ └── tsconfig.json │ │ ├── geojson/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ ├── map-style.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── geojson-animation/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── globe/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── heatmap/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ ├── control-panel.tsx │ │ │ │ └── map-style.ts │ │ │ └── tsconfig.json │ │ ├── interaction/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── layers/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── map-style-basic-v8.json │ │ ├── side-by-side/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── terrain/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ ├── viewport-animation/ │ │ │ ├── README.md │ │ │ ├── index.html │ │ │ ├── package.json │ │ │ ├── src/ │ │ │ │ ├── app.tsx │ │ │ │ └── control-panel.tsx │ │ │ └── tsconfig.json │ │ └── zoom-to-bounds/ │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app.tsx │ │ │ ├── control-panel.tsx │ │ │ └── map-style.tsx │ │ └── tsconfig.json │ └── vite.config.local.js ├── index.html ├── lerna.json ├── modules/ │ ├── main/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── mapbox-legacy/ │ │ │ │ ├── components/ │ │ │ │ │ ├── attribution-control.ts │ │ │ │ │ ├── fullscreen-control.ts │ │ │ │ │ ├── geolocate-control.ts │ │ │ │ │ ├── layer.ts │ │ │ │ │ ├── map.tsx │ │ │ │ │ ├── marker.ts │ │ │ │ │ ├── navigation-control.ts │ │ │ │ │ ├── popup.ts │ │ │ │ │ ├── scale-control.ts │ │ │ │ │ ├── source.ts │ │ │ │ │ ├── use-control.ts │ │ │ │ │ └── use-map.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── mapbox/ │ │ │ │ │ ├── create-ref.ts │ │ │ │ │ └── mapbox.ts │ │ │ │ ├── types/ │ │ │ │ │ ├── common.ts │ │ │ │ │ ├── events.ts │ │ │ │ │ ├── internal.ts │ │ │ │ │ ├── lib.ts │ │ │ │ │ └── style-spec.ts │ │ │ │ └── utils/ │ │ │ │ ├── apply-react-style.ts │ │ │ │ ├── assert.ts │ │ │ │ ├── deep-equal.ts │ │ │ │ ├── set-globals.ts │ │ │ │ ├── style-utils.ts │ │ │ │ ├── transform.ts │ │ │ │ └── use-isomorphic-layout-effect.ts │ │ │ ├── mapbox.ts │ │ │ └── maplibre.ts │ │ ├── test/ │ │ │ ├── components/ │ │ │ │ ├── controls.spec.jsx │ │ │ │ ├── index.js │ │ │ │ ├── layer.spec.jsx │ │ │ │ ├── map.spec.jsx │ │ │ │ ├── marker.spec.jsx │ │ │ │ ├── popup.spec.jsx │ │ │ │ ├── source.spec.jsx │ │ │ │ └── use-map.spec.jsx │ │ │ └── utils/ │ │ │ ├── apply-react-style.spec.js │ │ │ ├── deep-equal.spec.js │ │ │ ├── index.js │ │ │ ├── mapbox-gl-mock/ │ │ │ │ ├── edge_insets.js │ │ │ │ ├── lng_lat.js │ │ │ │ ├── lng_lat_bounds.js │ │ │ │ ├── transform.js │ │ │ │ └── util.js │ │ │ ├── style-utils.spec.js │ │ │ ├── test-utils.jsx │ │ │ └── transform.spec.js │ │ └── tsconfig.json │ ├── react-mapbox/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── components/ │ │ │ │ ├── attribution-control.ts │ │ │ │ ├── fullscreen-control.ts │ │ │ │ ├── geolocate-control.ts │ │ │ │ ├── layer.ts │ │ │ │ ├── map.tsx │ │ │ │ ├── marker.ts │ │ │ │ ├── navigation-control.ts │ │ │ │ ├── popup.ts │ │ │ │ ├── scale-control.ts │ │ │ │ ├── source.ts │ │ │ │ ├── use-control.ts │ │ │ │ └── use-map.tsx │ │ │ ├── index.ts │ │ │ ├── mapbox/ │ │ │ │ ├── create-ref.ts │ │ │ │ ├── mapbox.ts │ │ │ │ └── proxy-transform.ts │ │ │ ├── types/ │ │ │ │ ├── common.ts │ │ │ │ ├── events.ts │ │ │ │ ├── internal.ts │ │ │ │ ├── lib.ts │ │ │ │ └── style-spec.ts │ │ │ └── utils/ │ │ │ ├── apply-react-style.ts │ │ │ ├── assert.ts │ │ │ ├── compare-class-names.ts │ │ │ ├── deep-equal.ts │ │ │ ├── set-globals.ts │ │ │ ├── style-utils.ts │ │ │ ├── transform.ts │ │ │ └── use-isomorphic-layout-effect.ts │ │ ├── test/ │ │ │ ├── components/ │ │ │ │ ├── controls.spec.jsx │ │ │ │ ├── index.js │ │ │ │ ├── layer.spec.jsx │ │ │ │ ├── map.spec.jsx │ │ │ │ ├── marker.spec.jsx │ │ │ │ ├── popup.spec.jsx │ │ │ │ ├── source.spec.jsx │ │ │ │ └── use-map.spec.jsx │ │ │ └── utils/ │ │ │ ├── apply-react-style.spec.js │ │ │ ├── compare-class-names.spec.js │ │ │ ├── deep-equal.spec.js │ │ │ ├── index.js │ │ │ ├── mapbox-gl-mock/ │ │ │ │ ├── edge_insets.js │ │ │ │ ├── lng_lat.js │ │ │ │ ├── lng_lat_bounds.js │ │ │ │ ├── transform.js │ │ │ │ └── util.js │ │ │ ├── style-utils.spec.js │ │ │ ├── test-utils.jsx │ │ │ ├── token.js │ │ │ └── transform.spec.js │ │ └── tsconfig.json │ └── react-maplibre/ │ ├── package.json │ ├── src/ │ │ ├── components/ │ │ │ ├── attribution-control.ts │ │ │ ├── fullscreen-control.ts │ │ │ ├── geolocate-control.ts │ │ │ ├── globe-control.ts │ │ │ ├── layer.ts │ │ │ ├── logo-control.ts │ │ │ ├── map.tsx │ │ │ ├── marker.ts │ │ │ ├── navigation-control.ts │ │ │ ├── popup.ts │ │ │ ├── scale-control.ts │ │ │ ├── source.ts │ │ │ ├── terrain-control.ts │ │ │ ├── use-control.ts │ │ │ └── use-map.tsx │ │ ├── index.ts │ │ ├── maplibre/ │ │ │ ├── create-ref.ts │ │ │ └── maplibre.ts │ │ ├── types/ │ │ │ ├── common.ts │ │ │ ├── events.ts │ │ │ ├── internal.ts │ │ │ ├── lib.ts │ │ │ └── style-spec.ts │ │ └── utils/ │ │ ├── apply-react-style.ts │ │ ├── assert.ts │ │ ├── compare-class-names.ts │ │ ├── deep-equal.ts │ │ ├── set-globals.ts │ │ ├── style-utils.ts │ │ ├── transform.ts │ │ └── use-isomorphic-layout-effect.ts │ ├── test/ │ │ ├── .eslintrc │ │ ├── components/ │ │ │ ├── controls.spec.jsx │ │ │ ├── index.js │ │ │ ├── layer.spec.jsx │ │ │ ├── map.spec.jsx │ │ │ ├── marker.spec.jsx │ │ │ ├── popup.spec.jsx │ │ │ ├── source.spec.jsx │ │ │ └── use-map.spec.jsx │ │ └── utils/ │ │ ├── apply-react-style.spec.js │ │ ├── compare-class-names.spec.js │ │ ├── deep-equal.spec.js │ │ ├── index.js │ │ ├── style-utils.spec.js │ │ ├── test-utils.jsx │ │ └── transform.spec.js │ └── tsconfig.json ├── package.json ├── scripts/ │ └── update-release-branch.sh ├── test/ │ ├── .eslintrc │ ├── apps/ │ │ └── reuse-maps/ │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ └── app.tsx │ │ ├── tsconfig.json │ │ └── vite.config.js │ ├── browser.js │ ├── data/ │ │ ├── glyph/ │ │ │ └── UberMove/ │ │ │ └── 0-255 │ │ ├── sprite/ │ │ │ └── tools/ │ │ │ └── 14/ │ │ │ └── sprites.json │ │ ├── style.json │ │ └── tile/ │ │ └── v1/ │ │ └── 12/ │ │ └── 655/ │ │ ├── 1582/ │ │ │ ├── COMPOSITE │ │ │ └── POI │ │ └── 1583/ │ │ ├── COMPOSITE │ │ └── POI │ ├── node.js │ ├── render/ │ │ ├── index.jsx │ │ └── test-cases.jsx │ ├── size/ │ │ ├── mapbox-legacy.js │ │ ├── mapbox.js │ │ └── maplibre.js │ ├── src/ │ │ └── exports.ts │ └── test-utils.js ├── tsconfig.json └── website/ ├── .eslintignore ├── .gitignore ├── babel.config.js ├── docusaurus.config.js ├── package.json └── src/ ├── examples/ │ ├── index.mdx │ ├── mapbox/ │ │ ├── clusters.mdx │ │ ├── controls.mdx │ │ ├── custom-cursor.mdx │ │ ├── draggable-markers.mdx │ │ ├── draw-polygon.mdx │ │ ├── filter.mdx │ │ ├── geocoder.mdx │ │ ├── geojson-animation.mdx │ │ ├── geojson.mdx │ │ ├── heatmap.mdx │ │ ├── interaction.mdx │ │ ├── layers.mdx │ │ ├── side-by-side.mdx │ │ ├── terrain.mdx │ │ ├── viewport-animation.mdx │ │ └── zoom-to-bounds.mdx │ ├── maplibre/ │ │ ├── clusters.mdx │ │ ├── controls.mdx │ │ ├── custom-cursor.mdx │ │ ├── draggable-markers.mdx │ │ ├── draw-polygon.mdx │ │ ├── filter.mdx │ │ ├── geocoder.mdx │ │ ├── geojson-animation.mdx │ │ ├── geojson.mdx │ │ ├── heatmap.mdx │ │ ├── interaction.mdx │ │ ├── layers.mdx │ │ ├── side-by-side.mdx │ │ ├── terrain.mdx │ │ ├── viewport-animation.mdx │ │ └── zoom-to-bounds.mdx │ └── table-of-contents.json ├── mapbox-gl.css ├── maplibre-gl.css ├── pages/ │ └── index.jsx └── styles.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintignore ================================================ dist/ node_modules/ test/ modules/**/test/ **/vite.config.js examples/vite.config.local.js ================================================ FILE: .eslintrc.cjs ================================================ const {getESLintConfig} = require('@vis.gl/dev-tools/configuration'); module.exports = getESLintConfig({ react: '16.8.2', overrides: { parserOptions: { project: ['./tsconfig.json'], ecmaVersion: 2020 }, rules: { 'max-depth': ['warn', 4], complexity: ['warn'], 'max-statements': ['warn'], 'callback-return': 0 }, overrides: [ { files: ['**/*.ts', '**/*.tsx', '**/*.d.ts'], rules: { // Gradually enable '@typescript-eslint/ban-ts-comment': 0, '@typescript-eslint/ban-types': 0, '@typescript-eslint/no-unsafe-member-access': 0, '@typescript-eslint/no-unsafe-assignment': 0, 'import/named': 0, '@typescript-eslint/explicit-module-boundary-types': 0, '@typescript-eslint/no-unsafe-return': 0, '@typescript-eslint/no-unsafe-call': 0, '@typescript-eslint/restrict-plus-operands': 0, '@typescript-eslint/no-explicit-any': 0, '@typescript-eslint/no-unsafe-argument': 0, '@typescript-eslint/no-shadow': 1, '@typescript-eslint/no-redundant-type-constituents': 1 } } ] } }); ================================================ FILE: .github/ISSUE_TEMPLATE/bug-report.yml ================================================ name: Bug Report description: Something does not work as expected title: "[Bug]" labels: bug body: - type: markdown attributes: value: | Thank you for taking the time to report a bug! You may find answers faster by searching in [the documentation](https://visgl.github.io/react-map-gl/search) and [existing issues](https://github.com/visgl/react-map-gl/issue). If you are unsure whether it is a bug in your own implementation or the library itself, consider starting a conversation in [Discussions](https://github.com/visgl/react-map-gl/discussions) instead. - type: textarea attributes: label: Description description: What you're experiencing. validations: required: true - type: textarea attributes: label: Expected Behavior description: What you expect to see. validations: required: false - type: textarea attributes: label: Steps to Reproduce description: | Providing a Code Sandbox that reproduces the behavior. You can use [this boiler plate](https://codesandbox.io/s/react-map-gl-boiler-plate-717vw) as a starting point. validations: required: true - type: textarea attributes: label: Environment description: | Example: - **Framework version**: react-map-gl@7.0.0 - **Map library**: mapbox-gl@2.7.0 - **Browser**: Chrome 98.0 - **OS**: iOS 15.1 value: | - Framework version: - Map library: - Browser: - OS: validations: required: true - type: textarea attributes: label: Logs description: Check the browser console for any relevant errors or warnings. validations: required: false ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: I have a question / I need help url: https://github.com/visgl/react-map-gl/discussions about: Ask generic questions or request help here ================================================ FILE: .github/ISSUE_TEMPLATE/feature-request.yml ================================================ name: Feature Request description: Request for a new feature or enhancement title: "[Feat]" labels: feature body: - type: markdown attributes: value: | Tell us what you are using react-map-gl for and how we can make it better. This project is maintained by volunteers and sponsoring companies. While we cannot promise a timeline for any specific feature, we try to prioritize those that will benefit the most users. - type: textarea attributes: label: Target Use Case description: How would this benefit you and other developers? validations: required: true - type: textarea attributes: label: Proposal description: How would this feature work? If it's a new API, use code samples to show how it will be used. If it's visual, link to an image that illustrate the desired effect. validations: required: true ================================================ FILE: .github/SECURITY.md ================================================ # Security Policy ## Supported Versions Security updates are applied only to the latest release. ## Reporting a Vulnerability If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. Please disclose it at [security advisory](https://github.com/visgl/react-map-gl/security/advisories/new). This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. ================================================ FILE: .github/workflows/release.yml ================================================ name: release on: push: tags: - v* jobs: check_branch: runs-on: ubuntu-latest outputs: should_build: ${{ steps.permitted.outputs.result }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Fetch remote branches run: | git fetch origin --depth=1 - name: Check if on permitted branch id: permitted run: | result= if git branch -a --contains $GITHUB_SHA | grep -q 'remotes/origin/master$'; then result=true elif git branch -a --contains $GITHUB_SHA | grep -q 'remotes/origin/.*-release$'; then result=true fi echo "result=${result}" >> "$GITHUB_OUTPUT" release: runs-on: ubuntu-22.04 needs: check_branch permissions: contents: write if: ${{ github.repository_owner == 'visgl' && needs.check_branch.outputs.should_build }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_ACCESS_TOKEN: ${{ secrets.NPM_ACCESS_TOKEN }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version-file: '.nvmrc' cache: 'yarn' - name: Enable Corepack run: corepack enable yarn - name: Install dependencies run: yarn - name: Build packages run: yarn build - name: Run tests from transpiled code run: npx ocular-test dist - name: Login to NPM run: npm config set "//registry.npmjs.org/:_authToken=${NPM_ACCESS_TOKEN}" - name: Publish to NPM run: npx ocular-publish from-git ================================================ FILE: .github/workflows/test.yml ================================================ name: test # On every pull request, but only on push to master on: push: branches: - master pull_request: permissions: contents: read jobs: test-node: runs-on: ubuntu-22.04 permissions: checks: write contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Setup Node.js uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version-file: '.nvmrc' cache: 'yarn' - name: Enable Corepack run: corepack enable yarn - name: Install dependencies run: yarn bootstrap - name: Run tests env: VITE_MAPBOX_TOKEN: ${{ secrets.MAPBOX_ACCESS_TOKEN_CI }} run: | yarn lint yarn test ci - name: Coveralls uses: coverallsapp/github-action@648a8eb78e6d50909eff900e4ec85cab4524a45b # v2.3.6 with: github-token: ${{ secrets.GITHUB_TOKEN }} ================================================ FILE: .github/workflows/website.yml ================================================ name: website on: push: branches: - '*-release' jobs: check_branch: runs-on: ubuntu-22.04 outputs: should_deploy: ${{ endsWith(github.ref, steps.get_version.outputs.latest) }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Get version id: get_version run: | LATEST=$(npm show react-map-gl version | grep -o -E "^[0-9]+\.[0-9]+") echo "latest=${LATEST}-release" >> "$GITHUB_OUTPUT" deploy: runs-on: ubuntu-22.04 needs: check_branch permissions: contents: write if: ${{ github.repository_owner == 'visgl' && needs.check_branch.outputs.should_deploy }} steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: token: ${{ secrets.WEBSITE_DEPLOY_TOKEN }} - name: Setup Node.js uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: node-version-file: '.nvmrc' cache: 'yarn' - name: Enable Corepack run: corepack enable yarn - name: Install dependencies run: | yarn bootstrap (cd website && yarn) - name: Build website env: MapboxAccessToken: ${{ secrets.MAPBOX_ACCESS_TOKEN }} run: (cd website && yarn build) - name: Deploy uses: JamesIves/github-pages-deploy-action@132898c54c57c7cc6b80eb3a89968de8fc283505 # 3.7.1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: gh-pages FOLDER: website/build CLEAN: true ================================================ FILE: .gitignore ================================================ dist/ dist-es6/ node_modules .nyc_output/ coverage npm-debug.log package-lock.json examples/**/yarn.lock test/**/yarn.lock **/package-lock.json **/tsconfig.tsbuildinfo yarn-error.log .DS_Store .reify-cache tsconfig.tsbuildinfo .idea ================================================ FILE: .nvmrc ================================================ 18.19.0 ================================================ FILE: .ocularrc.js ================================================ /** @typedef {import('@vis.gl/dev-tools').OcularConfig} OcularConfig */ import {resolve} from 'path'; /** @type {OcularConfig} */ export default { lint: { paths: ['modules', 'test', 'examples'] }, coverage: { test: 'browser' }, aliases: { }, browserTest: { server: {wait: 5000} }, entry: { test: 'test/node.js', 'test-browser': 'test/browser.js', size: [ 'test/size/mapbox-legacy.js', 'test/size/maplibre.js', 'test/size/mapbox.js' ] } }; ================================================ FILE: .prettierrc ================================================ printWidth: 100 semi: true singleQuote: true trailingComma: none bracketSpacing: false arrowParens: avoid ================================================ FILE: CHANGELOG.md ================================================ # CHANGELOG # Version 8.1 ## v8.1.0-alpha.2 (Apr 9, 2025) - wrap jumpTo as internal update (#2516) ## v8.1.0-alpha.1 (Mar 28, 2025) - feat(mapbox): Replace shadow transform with proxied approach (#2514) # Version 8.0 ## v8.0.0-beta.1 (Jan 31, 2025) - feat: remove `RTLTextPlugin` default for MapLibre (#2480) ## v8.0.0-alpha.2 (Jan 27, 2025) - Migrate to monorepo (#2459) # Version 7.2 ## 7.2.0-beta.1 (Sep 12, 2023) - Switch to ESM module (#2281) # Version 7.1 ## 7.1.0-beta.3 (Jun 22, 2023) - Remap event types (#2207) - Restore fog, light and terrain types on MapProps (#2206) ## 7.1.0-beta.2 (Jun 14, 2023) - Make source prop of Layer optional (#2200) - Fix maplibre-gl peerDependencies typo (#2197) ## 7.1.0-beta.1 (Jun 5, 2023) - Add ref forwarding to Marker and Popup (#2191) - Split exports into separate endpoints (#2178) - Make mapbox-gl an optional dependency (#2175) - Remove defaultProps and displayName (#2173) # Version 7.0 ## 7.0.0 (Feb 4, 2022) v7 is a complete rewrite of the library. It addresses many long-standing issues in v5 and v6 limited by legacy architecture decisions. The most notable results of this redesign are: - Performance: minimize the overhead of React, offer the same fast and smooth interaction as the native library - Lightweight: the ESM build size is reduced from 219k to 57k - Predictability: Components behave the same as their mapbox counterparts. Props are mapped 1:1 from the native options wherever appropriate. Almost all imperative APIs (`flyTo`, `fitBounds` etc.) can now be called directly without breaking the React binding. - Compatibility: first and third-party plugins! Directly use [mapbox-gl-draw](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/draw-polygon), [mapbox-gl-geocoder](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/geocoder), to name a few. - TypeScript compliant: the code base is now entirely written in TypeScript, and all types can be [imported](/docs/api-reference/types.md). Visit the [upgrade guide](https://visgl.github.io/react-map-gl/docs/upgrade-guide) if you are trying to upgrade from v5 and v6. ## 7.0.0-beta.1 (Jan 26, 2022) - Add mapLib API (#1703) - Support inline styling for all components (#1702) - Refactor Mapbox class (#1701) ## 7.0.0-alpha.7 (Jan 17, 2022) - Improve typing (#1695) - [v7] Fix popup className update in mapbox v1/maplibre (#1694) ## 7.0.0-alpha.6 (Jan 9, 2022) - [v7] Fix double controls in strict mode (#1678) - [v7] Fix AttributionControl prop typo (#1679) ## 7.0.0-alpha.5 (Jan 6, 2022) - [v7] Handle unmount order (#1676) - [v7] Fix synchronization during transition (#1675) - [v7] Update MapRef (#1674) - [v7] Bug fixes (#1673) ## 7.0.0-alpha.4 (Jan 4, 2022) - [v7] Fix resize synchronization (#1670) - [v7] Add fog, light, terrain props (#1669) - [v7] support global settings with MapProps (#1668) ## 7.0.0-alpha.3 (Jan 3, 2022) - [v7] Clean up typings and expose more utility types (#1667) - Drop flow types support (#1666) ## 7.0.0-alpha.2 (Jan 2, 2022) - Update `@types/mapbox-gl` dependency ## 7.0.0-alpha.1 (Jan 2, 2022) - [v7] utility hooks (#1663) - [v7] Add Layer and Source (#1657) - [v7] Control components (#1656) - [v7] Marker and Popup (#1655) - [v7] Map component (#1652) - Typescript dev setup ================================================ FILE: CODE_OF_CONDUCT.md ================================================ # Code of Conduct react-map-gl is an [OpenJS Foundation](https://openjsf.org/) project. Please be mindful of and adhere to the OpenJS Foundation's [Code of Conduct](https://github.com/openjs-foundation/cross-project-council/blob/main/CODE_OF_CONDUCT.md) when contributing to react-map-gl. ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing **Thanks for taking the time to contribute!** PRs and bug reports are welcome, and we are actively looking for new maintainers. ## Setting Up Dev Environment The **master** branch is the active development branch. Building react-map-gl locally from the source requires node.js `>=8`. We use [yarn](https://yarnpkg.com/en/docs/install) to manage the dependencies. ```bash git checkout master yarn bootstrap yarn test ``` Test: ```bash $ yarn test ``` Test in Node: ```bash $ yarn test node ``` Test in browser (can use Chrome dev tools for debugging): ```bash $ yarn test browser ``` ## Pull Requests Any intended change to the code base must open a [pull request](https://help.github.com/articles/creating-a-pull-request/) and be approved. Generally speaking, all PRs are open against the `master` branch, unless the feature being affected no longer exists on master. ### PR Checklist - [ ] Tests - `yarn test` must be successful. + New code should be covered by unit tests whenever possible. - [ ] Documentation + If public APIs are added/modified, update component documentation in `docs/api-reference`. + Breaking changes and deprecations must be added to `docs/upgrade-guide.md`. + Noteworthy new features should be added to `docs/whats-new.md`. - [ ] Description on GitHub + Link to relevant issue. + Label with a milestone (latest release or vNext). + If public APIs are added/modified, describe the intended behavior. + If visual/interaction is affected, consider attaching a screenshot/GIF. ## Release react-map-gl follows the [Semantic Versioning](https://semver.org/) guidelines. Steps for publishing releases can be found [here](https://www.github.com/visgl/tsc/tree/master/developer-process). ## Community Governance vis.gl is part of the [OpenJS Foundation](https://openjsf.org/). See the organization's [Technical Charter](https://github.com/visgl/tsc/blob/master/Technical%20Charter.md). ### Technical Steering Committee react-map-gl development is governed by the vis.gl Technical Steering Committee (TSC). ### Maintainers - [Xiaoji Chen](https://github.com/Pessimistress) - [Xintong Xia](https://github.com/xintongxia) Maintainers of react-map-gl have commit access to this GitHub repository, and take part in the decision making process. If you are interested in becoming a maintainer, read the [governance guidelines](https://github.com/visgl/tsc/blob/master/governance.md). The vis.gl TSC meets monthly and publishes meeting notes via a [mailing list](https://lists.uc.foundation/g/visgl). This mailing list can also be utilized to reach out to the TSC. ================================================ FILE: LICENSE ================================================ Copyright Vis.gl contributors. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. This contains code from MapboxGL-js Copyright (c) 2014, Mapbox All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Mapbox GL JS nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- Contains code from Mapbox GL Style JSON Mapbox Open Styles are copyright (c) 2014, Mapbox, all rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: README.md ================================================

version build downloads

react-map-gl | Docs

`react-map-gl` is a suite of [React](https://react.dev/) components designed to provide a React API for [mapbox-gl](https://github.com/mapbox/mapbox-gl-js) or [maplibre-gl](https://maplibre.org/maplibre-gl-js/docs/). More information in the online documentation. See our [Design Philosophy](docs/README.md#design-philosophy). ### Installation Using `react-map-gl` requires `react >= 16.3`. ```sh # Using Maplibre npm install react-map-gl maplibre-gl ``` _or_ ```sh # Using Mapbox npm install react-map-gl mapbox-gl ``` ### Example ```js // Using Maplibre import * as React from 'react'; import Map from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ( ); } ``` _or_ ```js // Using Mapbox import * as React from 'react'; import Map from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ( ); } ``` Learn more with in our [Getting Started](https://visgl.github.io/react-map-gl/docs/get-started) guide. ### Contribute See [contribution guide](/CONTRIBUTING.md). ### Attributions react-map-gl is part of vis.gl, an [OpenJS Foundation](https://openjsf.org) project. Development is also supported by ================================================ FILE: TESTING.md ================================================ # Testing ## Unit, Lint ``` npm run test ``` ## Browser ``` npm run test-browser ``` **You'll need to specify a valid Mapbox Access Token in the URL** for the tests to pass. ``` http://localhost:8080/?access_token=MAPBOX_ACCESS_TOKEN ``` # Bumping Mapbox Version Always pin Mapbox to a specific release. The React controls (`NavigationControl`, `Popup` and `Marker`) are dependent on the Mapbox stylesheet, and may be broken by Mapbox updates. Always run `examples/controls` after bumping Mapbox version to make sure they still work. ================================================ FILE: docs/.gitignore ================================================ api-reference/web-mercator-viewport.md ================================================ FILE: docs/README.md ================================================ # Introduction > These docs are for v8.0. For v7, see [here](https://github.com/visgl/react-map-gl/tree/7.1-release/docs). react-map-gl is a suite of [React](http://facebook.github.io/react/) components for [mapbox-gl](https://www.npmjs.com/package/mapbox-gl), [maplibre-gl](https://www.npmjs.com/package/maplibre-gl) or compatible libraries. | Library | Description | | --- | --- | | [MapLibre GL JS](https://maplibre.org/maplibre-gl-js/docs/) | An Open-source TypeScript library for publishing web maps. | | [Mapbox GL JS](https://www.mapbox.com/mapbox-gljs) | A JavaScript library for interactive, customizable vector maps on the web. | | [Mapbox GL JS v1](https://github.com/mapbox/mapbox-gl-js/tree/release-v1.13.3) | The last free-open-source version of Mapbox GL JS. This version can be used without a Mapbox token if you do not use Mapbox hosted basemaps. | | Other compatible forks | It may be possible to use react-map-gl with mapbox-gl/maplibre-gl forks, but this is not a supported use case. Minor PRs to enable other forks to be used may be accepted. | If you need help choosing a base map library that is right for you: - Decide where to get your vector map data. + `mapbox-gl` is designed to work seamlessly with Mapbox's own data service. You will need a billable Mapbox token to use it. + There are a number of [map data providers](./get-started/mapbox-tokens.md#display-maps-without-a-mapbox-token) who support `maplibre-gl`, with a variaty of data quality and price options. + You can create and host your own map tiles and use them with `maplibre-gl` for (almost) free, if you are comfortable of using [open source tools](./get-started/mapbox-tokens.md#display-maps-without-a-mapbox-token) and setting up a cloud storage account. - Visit Mapbox and MapLibre websites for examples and documentation. Each library offer unique features that may not exist in another. New to react-map-gl? [Get Started](./get-started/get-started.md) Want to contribute? See our [Developer Guide](./contributing.md) ## Design Philosophy react-map-gl was first created by Uber's Visualization team, where Mapbox was used as a component to build powerful web tools such as [geospatial analytics](https://kepler.gl) and [self-driving data visualization](https://avs.auto/). To manage the complexity of these applications, we fully embrace React and reactive programming. The stock mapbox-gl APIs are [imperative](https://en.wikipedia.org/wiki/Imperative_programming). That is, you instruct the map to do something (for example, [map.flyTo](https://docs.mapbox.com/mapbox-gl-js/api/#map#flyto)), and it will execute the command at its own pace. This does not scale when we have many components that need to synchronize with each other. We sometimes render two maps side by side, and when the user interacts with one, update both cameras. We draw React UI outside of the map container, that moves with the camera. We also render WebGL graphic overlays on top of the map, most notably with [deck.gl](https://deck.gl). In these use cases, in order for all components to synchronize correctly, they must have their shared states managed by React. We might store the **source of truth** in a parent component state, or Redux store, or hooks, and let it propagate down to the map as well as its peers. Ultimately, in the spirit of the [reactive programming paradigm](https://en.wikipedia.org/wiki/Reactive_programming), data always flows **down**. As long as the map manages its own state, as mapbox-gl is designed to do, we risk the components going out of sync. react-map-gl creates a fully reactive wrapper for mapbox-gl/maplibre-gl. The [Map](./api-reference/maplibre/map.md) component can be fully [controlled](https://reactjs.org/docs/forms.html#controlled-components), that is, the map's camera would never deviate from the props that it's assigned. Read more about this core behavior in [state management](./get-started/state-management.md). ## Limitations In v7.0, react-map-gl was fully rewritten to better align its API with the underlying Mapbox GL JS library. Wherever the reactive usage patterns permits, the wrapper's props and methods are 1:1 mappings to their native API equivelants. It is possible to call the native methods directly from the `Map` instance obtained via [getMap](./api-reference/maplibre/map.md#gemap). However, doing so may result in the map's state to deviate from its props. For example, calling `map.setMaxZoom` directly will cause the map's constraint settings to differ from the value of the `maxZoom` prop. Generally speaking, calling a native method is disencouraged if the same thing can be achieved through the React interface. If a third-party plugin does so, then it may lead to some unexpected behaviors. ================================================ FILE: docs/api-reference/mapbox/attribution-control.md ================================================ # AttributionControl React component that wraps mapbox-gl's [AttributionControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#attributioncontrol) class. ```tsx import * as React from 'react'; import Map, {AttributionControl} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any options supported by the `AttributionControl` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#attributioncontrol) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/AttributionControl/)), such as - `compact` - `customAttribution` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'bottom-right'` Placement of the control relative to the map. ## Source [attribution-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/attribution-control.ts) ================================================ FILE: docs/api-reference/mapbox/fullscreen-control.md ================================================ # FullscreenControl React component that wraps mapbox-gl's [FullscreenControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#fullscreencontrol) class. ```tsx import * as React from 'react'; import Map, {FullscreenControl} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. #### `containerId`: string {#containerid} Id of the DOM element which should be made full screen. By default, the map container element will be made full screen. #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [fullscreen-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/fullscreen-control.ts) ================================================ FILE: docs/api-reference/mapbox/geolocate-control.md ================================================ # GeolocateControl React component that wraps mapbox-gl's [GeolocateControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#geolocatecontrol) class. ```tsx import * as React from 'react'; import Map, {GeolocateControl} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Callbacks #### `onGeolocate`: (evt: [GeolocateResultEvent](./types.md#geolocateresultevent)) => void {#ongeolocate} Called on each Geolocation API position update that returned as success. #### `onError`: (evt: [GeolocateErrorEvent](./types.md#geolocateerrorevent)) => void {#onerror} Called on each Geolocation API position update that returned as an error. #### `onOutOfMaxBounds`: (evt: [GeolocateResultEvent](./types.md#geolocateresultevent)) => void {#onoutofmaxbounds} Called on each Geolocation API position update that returned as success but user position is out of map `maxBounds`. #### `onTrackUserLocationStart`: (evt: [GeolocateEvent](./types.md#geolocateevent)) => void {#ontrackuserlocationstart} Called when the GeolocateControl changes to the active lock state. #### `onTrackUserLocationEnd`: (evt: [GeolocateEvent](./types.md#geolocateevent)) => void {#ontrackuserlocationend} Called when the GeolocateControl changes to the background state. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any options supported by the `GeolocateControl` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#geolocatecontrol) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/GeolocateControl/)), such as - `positionOptions` - `fitBoundsOptions` - `trackUserLocation` - `showAccuracyCircle` - `showUserLocation` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'bottom-right'` Placement of the control relative to the map. ## Methods The underlying native `GeolocateControl` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useEffect} from 'react'; import Map, {GeolocateControl} from 'react-map-gl/mapbox'; import type mapboxgl from 'mapbox-gl'; function App() { const geoControlRef = useRef(); useEffect(() => { // Activate as soon as the control is loaded geoControlRef.current?.trigger(); }, [geoControlRef.current]); return ; } ``` ## Source [geolocate-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/geolocate-control.ts) ================================================ FILE: docs/api-reference/mapbox/layer.md ================================================ # Layer This component allows apps to create a [map layer](https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers) using React. ```tsx import * as React from 'react'; import Map, {Layer} from 'react-map-gl/mapbox'; import type {FillLayer} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; const parkLayer: FillLayer = { id: 'landuse_park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#4E3FC8' } }; function App() { return ; } ``` ## Properties The props provided to this component should be conforming to the [Mapbox layer specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/#layers). When props change *shallowly*, the component will perform style diffing to update the layer. Avoid defining constant objects/arrays inline may help performance. ### Identity Properties Once a `` is mounted, the following props should not change. If you add/remove multiple JSX layers dynamically, make sure you use React's [key prop](https://reactjs.org/docs/lists-and-keys.html#keys) to give each element a stable identity. #### `id`: string {#id} Unique identifier of the layer. If not provided, a default id will be assigned. #### `type`: string {#type} Required. Type of the layer. ### Options #### `beforeId`: string {#beforeid} The ID of an existing layer to insert this layer before. If this prop is omitted, the layer will be appended to the end of the layers array. This is useful when using dynamic layers with a map style from a URL. Note that layers are added by the order that they mount. They are *NOT* reordered later if their relative positions in the JSX tree change. If dynamic reordering is desired, you should manipulate `beforeId` for consistent behavior. #### `source`: string {#source} `source` is required by some layer types in the Mapbox style specification. If `` is used as the immediate child of a [Source](./source.md) component, this prop will be overwritten by the id of the parent source. If the `` component is not an immediate descendant of ``, e.g wrapped inside a helper component, source property needs to be provided same as the id of the `` component for the `` component to show. ## Source [layer.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/layer.ts) ================================================ FILE: docs/api-reference/mapbox/map-provider.md ================================================ # MapProvider A [Context.Provider](https://reactjs.org/docs/context.html#contextprovider) that facilitates map operations outside of the component that directly renders a [Map](./map.md). The component should wrap all nodes in which you may want to access the maps: ```tsx import {MapProvider} from 'react-map-gl/mapbox'; function Root() { return ( { // Application tree, somewhere one or more component(s) are rendered } ); } ``` See [useMap](./use-map.md) for more information. ## Source [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/use-map.tsx) ================================================ FILE: docs/api-reference/mapbox/map.md ================================================ # default (Map) React component that wraps mapbox-gl's [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) class. This is also the default export from react-map-gl. ```tsx title="app.tsx" import * as React from 'react'; import Map from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ( ); } ``` ## Properties Aside from the props listed below, the `Map` component supports all parameters of the `Map` class constructor ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/map/) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/)). Beware that this is not an exhaustive list of all props. Different base map libraries may offer different options and default values. When in doubt, refer to your base map library's documentation. ### Layout options #### `id`: string {#id} Map container id. Required when [`MapProvider`](./map-provider.md)s are used. Used to reference the map with [`useMap`](./use-map.md). Make sure to pick a name that has no conflict with other imports (there are no checks or errors in this case). #### `style`: CSSProperties {#style} Default: `{position: 'relative', width: '100%', height: '100%'}` Map container CSS. #### `cursor`: string {#cursor} Default: `'auto'` The current cursor [type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor). ### Styling options #### `fog`: [Fog](./types.md#fog) {#fog} The fog property of the style. Must conform to the [Fog Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/fog/). If `undefined` is provided, removes the fog from the map. #### `light`: [Light](./types.md#light) {#light} Light properties of the style. Must conform to the [Light Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#light). #### `mapStyle`: [MapStyle](./types.md#mapstyle) | string | Immutable {#mapstyle} Default: (empty style) The map's Mapbox style. This must be an a JSON object conforming to the schema described in the [Mapbox Style Specification](https://mapbox.com/mapbox-gl-style-spec/), or a URL to such JSON. #### `projection`: string | [Projection](./types.md#projection) {#projection} Default: `'mercator'` The projection the map should be rendered in. Available projections are Albers (`'albers'`), Equal Earth (`'equalEarth'`), Equirectangular/Plate Carrée/WGS84 (`'equirectangular'`), Lambert (`'lambertConformalConic'`), Mercator (`'mercator'`), Natural Earth (`'naturalEarth'`), and Winkel Tripel (`'winkelTripel'`). Conic projections such as Albers and Lambert have configurable `center` and `parallels` properties that allow developers to define the region in which the projection has minimal distortion; see [example](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#setprojection). #### `renderWorldCopies`: boolean {#renderworldcopies} Default: `true` If `true`, multiple copies of the world will be rendered, when zoomed out. #### `styleDiffing`: boolean {#stylediffing} Default: `true` Enable diffing when `mapStyle` changes. If `false`, force a 'full' update, removing the current style and building the given one instead of attempting a diff-based update. #### `terrain`: [Terrain](./types.md#terrain) {#terrain} Terrain property of the style. Must conform to the [Terrain Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/terrain/). If `undefined` is provided, removes terrain from the map. ### Camera options #### `initialViewState`: object {#initialviewstate} The initial view state of the map. If specified, `longitude`, `latitude`, `zoom` etc. in props are ignored when constructing the map. Only specify `initialViewState` if `Map` is being used as an **uncontrolled component**. See [state management](../../get-started/state-management.md) for examples. - `bounds`: [LngLatBoundsLike](./types.md#lnglatboundslike) - The initial bounds of the map. If specified, it overrides the `longitude`, `latitude` and `zoom` options. Default `null`. - `fitBoundsOptions` - An object to use only when setting the `bounds` option. Default `null`. + `fitBoundsOptions.offset`: [PointLike](./types.md#pointlike) + `fitBoundsOptions.minZoom`: number + `fitBoundsOptions.maxZoom`: number + `fitBoundsOptions.padding`: [PaddingOptions](./types.md#paddingoptions) - `longitude`: number - The initial longitude of the map center. Default `0`. - `latitude`: number - The initial latitude of the map center. Default `0`. - `zoom`: number - The initial zoom level. Default `0`. - `pitch`: number - The initial pitch (tilt) of the map. Default `0`. - `bearing`: number - The initial bearing (rotation) of the map. Default `0`. #### `longitude`: number {#longitude} The longitude of the map center. #### `latitude`: number {#latitude} The latitude of the map center. #### `zoom`: number {#zoom} The [zoom level](https://docs.mapbox.com/help/glossary/camera/#zoom-level) of the map. #### `pitch`: number {#pitch} The initial [pitch](https://docs.mapbox.com/help/glossary/camera/#pitch) (tilt) of the map, measured in degrees away from the plane of the screen (0-85). #### `bearing`: number {#bearing} The initial [bearing](https://docs.mapbox.com/help/glossary/camera/#bearing) (rotation) of the map, measured in degrees counter-clockwise from north. #### `padding`: [PaddingOptions](./types.md#paddingoptions) {#padding} Default: `null` The padding in pixels around the viewport. #### `minZoom`: number {#minzoom} Default: `0` The minimum zoom level of the map (0-24). #### `maxZoom`: number {#maxzoom} Default: `22` The maximum zoom level of the map (0-24). #### `minPitch`: number {#minpitch} Default: `0` The minimum pitch of the map (0-85). #### `maxPitch`: number {#maxpitch} Default: `60` The maximum pitch of the map (0-85). #### `maxBounds`: [LngLatBoundsLike](./types.md#lnglatboundslike) {#maxbounds} Default: `null` If set, the map is constrained to the given bounds. ### Input handler options #### `boxZoom`: boolean {#boxzoom} Default: `true` If `true`, the "box zoom" interaction is enabled. See `BoxZoomHandler` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#boxzoomhandler) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/BoxZoomHandler/)) #### `doubleClickZoom`: boolean {#doubleclickzoom} Default: `true` If `true`, the "double click to zoom" interaction is enabled. See `DoubleClickZoomHandler` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#doubleclickzoomhandler) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/DoubleClickZoomHandler/)). #### `dragRotate`: boolean {#dragrotate} Default: `true` If `true`, the "drag to rotate" interaction is enabled. See `DragRotateHandler` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#dragrotatehandler) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/DragRotateHandler/)). #### `dragPan`: boolean | Object {#dragpan} Default: `true` If `true`, the "drag to pan" interaction is enabled. Optionally accept an object value that is the options to `DragPanHandler.enable` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#dragpanhandler#enable) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/DragPanHandler/#enable)). #### `keyboard`: boolean {#keyboard} Default: `true` If `true`, keyboard shortcuts are enabled. See `KeyboardHandler` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#keyboardhandler) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/KeyboardHandler/)). #### `scrollZoom`: boolean | Object {#scrollzoom} Default: `true` If `true`, the "scroll to zoom" interaction is enabled. Optionally accept an object value that is the options to `ScrollZoomHandler.enable` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#scrollzoomhandler#enable) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/ScrollZoomHandler/#enable)) #### `touchPitch`: boolean | Object {#touchpitch} Default: `true` If `true`, the "drag to pitch" interaction is enabled. Optionally accept an object value that is the options to `TouchPitchHandler.enable`([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#touchpitchhandler) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/TwoFingersTouchPitchHandler/#enable)). #### `touchZoomRotate`: boolean | Object {#touchzoomrotate} Default: `true` If `true`, the "pinch to rotate and zoom" interaction is enabled. Optionally accept an object value that is the options to `TouchZoomRotateHandler.enable` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/handlers/#touchzoomrotatehandler#enable) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/TwoFingersTouchZoomRotateHandler/#enable)). #### `interactiveLayerIds`: string[] {#interactivelayerids} Default: `null` The id(s) of style layer(s). If specified, pointer event (`mousemove`, `click` etc.) listeners will be triggered only if its location is within a visible feature in these layers, and the event will have a `features` property containing an array of the matching features. If not specified, pointer event listeners will be triggered by a corresponding event happening anywhere on the map, and the event will not have a `features` property. See the [Callbacks](#callbacks) section for affected events. ### Callbacks #### `onResize`: (event: [MapEvent](./types.md#mapevent)) => void {#onresize} Called when the map has been resized. #### `onLoad`: (event: [MapEvent](./types.md#mapevent)) => void {#onload} Called after all necessary resources have been downloaded and the first visually complete rendering of the map has occurred. #### `onRender`: (event: [MapEvent](./types.md#mapevent))) => void {#onrender} Called whenever the map is drawn to the screen. #### `onIdle`: (event: [MapEvent](./types.md#mapevent))) => void {#onidle} Called after the last frame rendered before the map enters an "idle" state: - No camera transitions are in progress - All currently requested tiles have loaded - All fade/transition animations have completed #### `onRemove`: (event: [MapEvent](./types.md#mapevent))) => void {#onremove} Called when the map has been removed. #### `onError`: (event: [ErrorEvent](./types.md#errorevent)) => void {#onerror} Default: `evt => console.error(evt.error)` Called when an error occurs. #### `onMouseDown`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmousedown} Called when a pointing device (usually a mouse) is pressed within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onMouseUp`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseup} Called when a pointing device (usually a mouse) is released within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onMouseOver`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseover} Called when a pointing device (usually a mouse) is moved within the map. As you move the cursor across a web page containing a map, the event will fire each time it enters the map or any child elements. #### `onMouseEnter`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseenter} Called when a pointing device (usually a mouse) enters a visible portion of the layer(s) specified by `interactiveLayerIds` from outside that layer or outside the map canvas. #### `onMouseMove`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmousemove} Called when a pointing device (usually a mouse) is moved while the cursor is inside the map. As you move the cursor across the map, the event will fire every time the cursor changes position within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onMouseLeave`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseleave} Called when a pointing device (usually a mouse) leaves a visible portion of the layer(s) specified by `interactiveLayerIds` or moves from the layer to outside the map canvas. #### `onMouseOut`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseout} Called when a point device (usually a mouse) leaves the map's canvas. #### `onClick`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onclick} Called when a pointing device (usually a mouse) is pressed and released at the same point on the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onDblClick`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#ondblclick} Called when a pointing device (usually a mouse) is pressed and released twice at the same point on the map in rapid succession. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onContextMenu`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#oncontextmenu} Called when the right button of the mouse is clicked or the context menu key is pressed within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onWheel`: (event: [MapWheelEvent](./types.md#mapwheelevent)) => void {#onwheel} Called when a wheel event occurs within the map. #### `onTouchStart`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchstart} Called when a `touchstart` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onTouchEnd`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchend} Called when a `touchend` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onTouchMove`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchmove} Called when a `touchmove` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onTouchCancel`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchcancel} Called when a `touchcancel` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layers. #### `onMoveStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmovestart} Called just before the map begins a transition from one view to another. #### `onMove`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmove} Called repeatedly during an animated transition from one view to another. When `Map` is used as a controlled component, `event.viewState` reflects the view state that the camera "proposes" to move to, as a result of either user interaction or methods such as [flyTo](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto). The camera does not actually change until the application updates the view state props (`longitude`, `latitude`, `zoom` etc.). See [state management](../../get-started/state-management.md) for examples. #### `onMoveEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmoveend} Called just after the map completes a transition from one view to another. #### `onDragStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondragstart} Called when a "drag to pan" interaction starts. #### `onDrag`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondrag} Called repeatedly during a "drag to pan" interaction. #### `onDragEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondragend} Called when a "drag to pan" interaction ends. #### `onZoomStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoomstart} Called just before the map begins a transition from one zoom level to another. #### `onZoom`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoom} Called repeatedly during an animated transition from one zoom level to another. When `Map` is used as a controlled component, `event.viewState.zoom` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto). The camera does not actually change until the application updates the `zoom` prop. #### `onZoomEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoomend} Called just after the map completes a transition from one zoom level to another. #### `onRotateStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotatestart} Called just before the map begins a transition from one bearing (rotation) to another. #### `onRotate`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotate} Called repeatedly during an animated transition from one bearing (rotation) to another. When `Map` is used as a controlled component, `event.viewState.bearing` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto). The camera does not actually change until the application updates the `bearing` prop. #### `onRotateEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotateend} Called just after the map completes a transition from one bearing (rotation) to another. #### `onPitchStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitchstart} Called just before the map begins a transition from one pitch (tilt) to another. #### `onPitch`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitch} Called repeatedly during an animated transition from one pitch (tilt) to another. When `Map` is used as a controlled component, `event.viewState.pitch` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://docs.mapbox.com/mapbox-gl-js/api/map/#map#flyto). The camera does not actually change until the application updates the `pitch` prop. #### `onPitchEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitchend} Called just after the map completes a transition from one pitch (tilt) to another. #### `onBoxZoomStart`: (event: [MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomstart} Called when a "box zoom" interaction starts. #### `onBoxZoomEnd`: (event: [MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomend} Called when a "box zoom" interaction ends. #### `onBoxZoomCancel`: (event:[MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomcancel} Called when the user cancels a "box zoom" interaction, or when the bounding box does not meet the minimum size threshold. #### `onData`: (event: [MapStyleDataEvent](./types.md#mapstyledataevent) | [MapSourceDataEvent](./types.md#mapsourcedataevent)) => void {#ondata} Called when any map data loads or changes. See [MapDataEvent](https://docs.mapbox.com/mapbox-gl-js/api/events/#mapdataevent) for more information. #### `onStyleData`: (event: [MapStyleDataEvent](./types.md#mapstyledataevent)) => void {#onstyledata} Called when the map's style loads or changes. See [MapDataEvent](https://docs.mapbox.com/mapbox-gl-js/api/events/#mapdataevent) for more information. #### `onSourceData`: (event: [MapSourceDataEvent](./types.md#mapsourcedataevent)) => void {#onsourcedata} Called when one of the map's sources loads or changes, including if a tile belonging to a source loads or changes. See [MapDataEvent](https://docs.mapbox.com/mapbox-gl-js/api/events/#mapdataevent) for more information. ### Other options The following props, along with any options of the `Map` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/map/) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/)) not listed above, can be specified to construct the underlying `Map` instance. Note: props in this section are not reactive. They are only used once when the Map instance is constructed. #### `mapLib`: any {#maplib} Default: - `import('mapbox-gl')` if imported from `react-map-gl` - `import('maplibre-gl')` if imported from `react-map-gl/maplibre` Specify the underlying base map library for the Map component. The value can be provided with several options: By module import (and embedding in the final bundle): ```tsx import * as React from 'react'; import Map from 'react-map-gl/mapbox'; import mapboxgl from 'mapbox-gl'; function App() { return ; } ``` By dynamic import (thus enable bundle splitting): ```tsx import * as React from 'react'; import Map from 'react-map-gl/mapbox'; function App() { return ; } ``` Or to load a pre-bundled version of the library: ```html title="index.html" ``` ```tsx title="app.tsx" import * as React from 'react'; import Map from 'react-map-gl/mapbox'; function App() { return ; } ``` #### `mapboxAccessToken`: string {#mapboxaccesstoken} Token used to access the Mapbox data service. See [about map tokens](../../get-started/mapbox-tokens.md). #### `baseApiUrl`: string {#baseapiurl} The map's default API URL for requesting tiles, styles, sprites, and glyphs. #### `maxParallelImageRequests`: number {#maxparallelimagerequests} Default: `16` The maximum number of images (raster tiles, sprites, icons) to load in parallel. #### `reuseMaps`: boolean {#reusemaps} Default: `false` By default, every time a map component is unmounted, all internal resources associated with the underlying `Map` instance are released. If the map gets mounted again, a new `Map` instance is constructed. If `reuseMaps` is set to `true`, when a map component is unmounted, the underlying `Map` instance is retained in memory. The next time a map component gets mounted, the saved instance is reused. This behavior may be desirable if an application frequently mounts/unmounts map(s), for example in a tabbed or collapsable UI, and wants to avoid Mapbox's [billable events](https://github.com/mapbox/mapbox-gl-js/releases/tag/v2.0.0) triggered by initialization. Note that since some map options cannot be modified after initialization, when reusing maps, only the reactive props and `initialViewState` of the new component are respected. #### `RTLTextPlugin`: string | false {#rtltextplugin} Default: `'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js'` Sets the map's [RTL text plugin](https://www.mapbox.com/mapbox-gl-js/plugins/#mapbox-gl-rtl-text). Necessary for supporting the Arabic and Hebrew languages, which are written right-to-left. Setting this prop is the equivalent of calling [mapboxgl.setRTLTextPlugin](https://docs.mapbox.com/mapbox-gl-js/api/properties/#setrtltextplugin) with `lazy: true`. Set to `false` to disable loading the RTL text plugin. #### `workerClass`: object {#workerclass} Default: `null` Provides an interface for external module bundlers such as Webpack or Rollup to package mapbox-gl's WebWorker into a separate class and integrate it with the library. Takes precedence over `workerUrl`. #### `workerCount`: number {#workercount} Default: `2` The number of web workers instantiated on a page with mapbox-gl maps. #### `workerUrl`: string {#workerurl} Provides an interface for loading mapbox-gl's WebWorker bundle from a self-hosted URL. This is useful if your site needs to operate in a strict CSP (Content Security Policy) environment wherein you are not allowed to load JavaScript code from a Blob URL, which is default behavior. ## Methods Imperative methods are accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or the [useMap](./use-map.md) hook. ```tsx import * as React from 'react'; import {useRef, useCallback} from 'react'; import Map from 'react-map-gl/mapbox'; import type {MapRef} from 'react-map-gl/mapbox'; function App() { const mapRef = useRef(null); const onMapLoad = useCallback(() => { mapRef.current.on('move', () => { // do something }); }, []); return ; } ``` The [MapRef](./types.md#mapref) object exposes Map methods ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/map/#map-instance-members) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#methods)) that **are safe to call without breaking the React bindings**. For example, `setStyle()` is hidden from the ref object, because the style is supposed to be changed by updating the `mapStyle` prop. Calling the method directly may cause the the React prop to mismatch with the underlying state, and lead to unexpected behaviors. You can still access the hidden members via `getMap()`: #### `getMap()` {#getmap} Returns the native `Map` ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/map/) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/)) instance associated with this component. ## Source [map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/map.tsx) ================================================ FILE: docs/api-reference/mapbox/marker.md ================================================ # Marker React component that wraps mapbox-gl's [Marker](https://docs.mapbox.com/mapbox-gl-js/api/markers/#marker) class. ```tsx import * as React from 'react'; import Map, {Marker} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` If `Marker` is mounted with child components, then its content will be rendered to the specified location. If it is mounted with no content, then a default marker will be used. ## Properties ### Reactive Properties #### `draggable`: boolean {#draggable} Default: `false` If `true`, the marker is able to be dragged to a new position on the map. #### `latitude`: number {#latitude} Required. The latitude of the anchor location. #### `longitude`: number {#longitude} Required. The longitude of the anchor location. #### `offset`: [PointLike](./types.md#pointlike) {#offset} Default: `null` The offset in pixels as a [PointLike](https://docs.mapbox.com/mapbox-gl-js/api/geography/#pointlike) object to apply relative to the element's center. Negatives indicate left and up. #### `pitchAlignment`: 'map' | 'viewport' | 'auto' {#pitchalignment} Default: `'auto'` - `map` aligns the `Marker` to the plane of the map. - `viewport` aligns the `Marker` to the plane of the viewport. - `auto` automatically matches the value of `rotationAlignment`. #### `popup`: Popup | null {#popup} An instance of the `Popup` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#popup) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/classes/Popup/)) to attach to this marker. If undefined or null, any popup set on this Marker instance is unset. #### `rotation`: number {#rotation} Default: `0` The rotation angle of the marker in degrees, relative to its `rotationAlignment` setting. A positive value will rotate the marker clockwise. #### `rotationAlignment`: 'map' | 'viewport' | 'auto' {#rotationalignment} Default: `'auto'` - `map` aligns the `Marker`'s rotation relative to the map, maintaining a bearing as the map rotates. - `viewport` aligns the `Marker`'s rotation relative to the viewport, agnostic to map rotations. - `auto` is equivalent to `viewport`. #### `style`: CSSProperties {#style} CSS style override that applies to the marker's container. ### Callbacks #### `onClick`: (evt: [MapEvent](./types.md#mapevent)) => void {#onclick} Called when the marker is clicked on. #### `onDragStart`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondragstart} Called when dragging starts, if `draggable` is `true`. #### `onDrag`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondrag} Called while dragging, if `draggable` is `true`. #### `onDragEnd`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondragend} Called when dragging ends, if `draggable` is `true`. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any options supported by the `Marker` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#marker) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MarkerOptions/)), such as - `anchor` - `color` - `scale` - `clickTolerance` ## Methods The underlying native `Marker` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useMemo, useCallback} from 'react'; import Map, {Marker} from 'react-map-gl/mapbox'; import mapboxgl from 'mapbox-gl'; function App() { const markerRef = useRef(); const popup = useMemo(() => { return mapboxgl.Popup().setText('Hello world!'); }, []) const togglePopup = useCallback(() => { markerRef.current?.togglePopup(); }, []); return <> ; } ``` ## Source [marker.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/marker.ts) ================================================ FILE: docs/api-reference/mapbox/navigation-control.md ================================================ # NavigationControl React component that wraps mapbox-gl's [NavigationControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#navigationcontrol) class. ```tsx import * as React from 'react'; import Map, {NavigationControl} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any options supported by the `NavigationControl` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#navigationcontrol) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/NavigationControlOptions/)), such as - `showCompass` - `showZoom` - `visualizePitch` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [navigation-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/navigation-control.ts) ================================================ FILE: docs/api-reference/mapbox/popup.md ================================================ # Popup React component that wraps mapbox-gl's [Popup](https://docs.mapbox.com/mapbox-gl-js/api/markers/#popup) class. ```tsx import * as React from 'react'; import {useState} from 'react'; import Map, {Popup} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { const [showPopup, setShowPopup] = useState(true); return {showPopup && ( setShowPopup(false)}> You are here )} ; } ``` ## Properties ### Reactive Properties #### `anchor`: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | undefined {#anchor} A string indicating the part of the popup that should be positioned closest to the coordinate, set via `longitude` and `latitude`. If unset, the anchor will be dynamically set to ensure the popup falls within the map container with a preference for `'bottom'`. #### `className`: string {#classname} Space-separated CSS class names to add to popup container. #### `offset`: number | [PointLike](./types.md#pointlike) | Record\ {#offset} Default: `null` A pixel offset applied to the popup's location specified as: - a single number specifying a distance from the popup's location - a PointLike specifying a constant offset - an object of Points specifing an offset for each anchor position. Negative offsets indicate left and up. #### `maxWidth`: string {#maxwidth} Default: `240px` A string that sets the CSS property of the popup's maximum width. #### `style`: CSSProperties {#style} CSS style override that applies to the popup's container. ### Callbacks #### `onOpen`: (evt: [PopupEvent](./types.md#popupevent)) => void {#onopen} Called when the popup is opened. #### `onClose`: (evt: [PopupEvent](./types.md#popupevent)) => void {#onclose} Called when the popup is closed by the user clicking on the close button or outside (if `closeOnClick: true`). ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any options supported by the `Popup` class ([Mapbox](https://docs.mapbox.com/mapbox-gl-js/api/markers/#popup) | [Maplibre](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/PopupOptions/)), such as - `closeButton` - `closeOnClick` - `closeOnMove` - `focusAfterOpen` ## Methods The underlying native `Popup` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useEffect} from 'react'; import Map, {Popup} from 'react-map-gl/mapbox'; import mapboxgl from 'mapbox-gl'; function App() { const popupRef = useRef(); useEffect(() => { popupRef.current?.trackPointer(); }, [popupRef.current]) return Tooltip ; } ``` ## Source [popup.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/popup.ts) ================================================ FILE: docs/api-reference/mapbox/scale-control.md ================================================ # ScaleControl React component that wraps mapbox-gl's [ScaleControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#scalecontrol) class. ```tsx import * as React from 'react'; import Map, {ScaleControl} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `maxWidth`: string {#maxwidth} Default: `100` The maximum length of the scale control in pixels. #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. #### `unit`: 'imperial' | 'metric' | 'nautical' {#unit} Default: `'metric'` Unit of the distance. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [scale-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/scale-control.ts) ================================================ FILE: docs/api-reference/mapbox/source.md ================================================ # Source This component allows apps to create a [map source](https://docs.mapbox.com/mapbox-gl-js/style-spec/#sources) using React. It may contain [Layer](./layer.md) components as children. ```tsx import * as React from 'react'; import Map, {Source, Layer} from 'react-map-gl/mapbox'; import type {CircleLayer} from 'react-map-gl/mapbox'; import type {FeatureCollection} from 'geojson'; import 'mapbox-gl/dist/mapbox-gl.css'; const geojson: FeatureCollection = { type: 'FeatureCollection', features: [ {type: 'Feature', geometry: {type: 'Point', coordinates: [-122.4, 37.8]}} ] }; const layerStyle: CircleLayer = { id: 'point', type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; function App() { return ; } ``` ## Properties The props provided to this component should be conforming to the [Mapbox source specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/#sources) or [CanvasSourceOptions](https://docs.mapbox.com/mapbox-gl-js/api/#canvassourceoptions). When props change _shallowly_, the component will attempt to update the source. Do not define objects/arrays inline to avoid perf hit. Once a `` is mounted, the following props should not change. If add/remove multiple JSX sources dynamically, make sure you use React's [key prop](https://reactjs.org/docs/lists-and-keys.html#keys) to give each element a stable identity. #### `id`: string {#id} Unique identifier of the source. If not provided, a default id will be assigned. #### `type`: string {#type} Required. Type of the source. ## Source [source.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/source.ts) ================================================ FILE: docs/api-reference/mapbox/types.md ================================================ # Types The following types can be imported from `react-map-gl/mapbox` when using TypeScript. ## Components #### IControl A [custom control implementation](https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol). #### CustomLayerInterface A [custom layer implementation](https://docs.mapbox.com/mapbox-gl-js/api/#customlayerinterface). #### MapRef Instance [ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) of a `Map` component. See [Map documentation](./map.md#methods) for details. ## Styling #### StyleSpecification An object conforming to the [Mapbox Style Specification](https://mapbox.com/mapbox-gl-style-spec/). #### FogSpecification An object conforming to the [Fog Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/fog/). #### LightSpecification An object conforming to the [Light Style Specification](https://www.mapbox.com/mapbox-gl-style-spec/#light). #### TerrainSpecification An object conforming to the [Terrain Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/terrain/). #### ProjectionSpecification An object conforming to the [Projection Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/projection/). #### BackgroundLayerSpecification A JSON object that defines a `background` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#background). #### CircleLayerSpecification A JSON object that defines a `circle` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#circle). #### FillExtrusionLayerSpecification A JSON object that defines a `fill-extrusion` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#fill-extrusion). #### FillLayerSpecification A JSON object that defines a `fill` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#fill). #### HeatmapLayerSpecification A JSON object that defines a `heatmap` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#heatmap). #### HillshadeLayerSpecification A JSON object that defines a `hillshade` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#hillshade). #### LineLayerSpecification A JSON object that defines a `line` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#line). #### RasterLayerSpecification A JSON object that defines a `raster` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#raster). #### SymbolLayerSpecification A JSON object that defines a `symbol` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#symbol). #### SkyLayerSpecification A JSON object that defines a `sky` layer according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#sky). #### GeoJSONSourceSpecification A JSON object that defines a `geojson` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#geojson). #### VideoSourceSpecification A JSON object that defines a `video` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#video). #### ImageSourceSpecification A JSON object that defines a `image` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#image). #### VectorSourceSpecification A JSON object that defines a `vector` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#vector). #### RasterSourceSpecification A JSON object that defines a `raster` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#raster). #### RasterDEMSourceSpecification A JSON object that defines a `raster-dem` source according to the [Mapbox Style Specification](https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/#raster-dem). #### CanvasSourceSpecification A JSON object that defines a `canvas` source type. See [CanvasSourceOptions](https://docs.mapbox.com/mapbox-gl-js/api/sources/#canvassourceoptions). ## Configurations #### ControlPosition One of `'top-right'`, `'top-left'`, `'bottom-right'` and `'bottom-left'`. #### PaddingOptions An object with the following fields: - `left`: number - in pixels. - `top`: number - in pixels. - `right`: number - in pixels. - `bottom`: number - in pixels. ## Data Types #### LngLat A Mapbox [LngLat](https://docs.mapbox.com/mapbox-gl-js/api/geography/#lnglat) object. #### LngLatLike A Mapbox [LngLatLike](https://docs.mapbox.com/mapbox-gl-js/api/geography/#lnglatlike) object. #### LngLatBounds A Mapbox [LngLatBounds](https://docs.mapbox.com/mapbox-gl-js/api/geography/#lnglatbounds) object. #### LngLatBoundsLike A Mapbox [LngLatBoundsLike](https://docs.mapbox.com/mapbox-gl-js/api/geography/#lnglatboundslike) object. #### Point A Mapbox [Point](https://docs.mapbox.com/mapbox-gl-js/api/geography/#point) object. #### PointLike A Mapbox [PointLike](https://docs.mapbox.com/mapbox-gl-js/api/geography/#pointlike) object. #### MapGeoJSONFeature A [GeoJSON](http://geojson.org/) feature that also contains the following library-specific fields: - `layer`: Layer - `source`: string - `sourceLayer`: string - `state`: `{ [key: string]: any }` #### ViewState An object with the following fields: - `longitude`: number - The longitude of the map center. - `latitude`: number - The latitude of the map center. - `zoom`: number - The zoom level. - `pitch`: number - The pitch (tilt) of the map, in degrees. - `bearing`: number - The bearing (rotation) of the map, in degrees. - `elevation`: number|undefined - The map center elevation from sea leavel on terrain surface, if any ## Events #### MapEvent An object with the following fields: - `type`: string - Event type - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `originalEvent?`: [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) #### MapLayerMouseEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `originalEvent?`: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) - `point`: [Point](#point) - `lngLat`: [LngLat](#lnglat) - `preventDefault`: () => void - `defaultPrevented`: boolean - `features?`: [MapGeoJSONFeature](#mapgeojsonfeature)[] #### MapWheelEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `originalEvent?`: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) - `preventDefault`: () => void - `defaultPrevented`: boolean #### MapLayerTouchEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `originalEvent?`: [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) - `point`: [Point](#point) - `lngLat`: [LngLat](#lnglat) - `points`: [Point](#point)[] - `lngLats`: [LngLat](#lnglat)[] - `preventDefault`: () => void - `defaultPrevented`: boolean - `features?`: [MapGeoJSONFeature](#mapgeojsonfeature)[] #### ViewStateChangeEvent An object with the following fields: - `type`: string - Event type - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `viewState`: [ViewState](#viewstate) - the next view state that the camera wants to change to based on user input or transition. #### MapBoxZoomEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `originalEvent?`: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) - `boxZoomBounds`: [LngLatBounds](#lnglatbounds) #### MapStyleDataEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `dataType`: 'style' #### MapSourceDataEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `dataType`: 'source' - `isSourceLoaded`: boolean - `source`: string - `sourceId`: string - `sourceDataType`: 'metadata' | 'content' - `tile`: any - `coord`: Coordinate See [MapDataEvent](https://docs.mapbox.com/mapbox-gl-js/api/events/#mapdataevent). #### ErrorEvent An object with the following fields: - `type`: 'error' - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `error`: [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) #### GeolocateEvent An object with the following fields: - `type`: string - `target`: [Map](https://docs.mapbox.com/mapbox-gl-js/api/map/) - `target`: [GeolocateControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#geolocatecontrol) #### GeolocateResultEvent An object with the following fields: - `type`: string - `target`: [GeolocateControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#geolocatecontrol) - `coords`: [GeolocationCoordinates](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates) - the current location. - `timestamp`: number - the time at which the location was retrieved. #### GeolocateErrorEvent An object with the following fields: - `type`: string - `target`: [GeolocateControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#geolocatecontrol) - `code`: PERMISSION_DENIED | POSITION_UNAVAILABLE | TIMEOUT - see [GeolocationPositionError](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError) - `message`: string - the details of the error. Specifications note that this is primarily intended for debugging use and not to be shown directly in a user interface. #### MarkerEvent An object with the following fields: - `type`: string - `target`: [Marker](https://docs.mapbox.com/mapbox-gl-js/api/markers/#marker) #### MarkerDragEvent An object with the following fields: - `type`: string - `target`: [Marker](https://docs.mapbox.com/mapbox-gl-js/api/markers/#marker) - `lngLat`: [LngLat](#lnglat) - the new location of the marker #### PopupEvent An object with the following fields: - `type`: string - `target`: [Popup](https://docs.mapbox.com/mapbox-gl-js/api/markers/#popup) ================================================ FILE: docs/api-reference/mapbox/use-control.md ================================================ # useControl The `useControl` hook is used to create React wrappers for custom map controls. ```tsx import MapboxDraw from '@mapbox/mapbox-gl-draw'; import Map, {useControl} from 'react-map-gl/mapbox'; function DrawControl(props: DrawControlProps) { useControl(() => new MapboxDraw(props), { position: props.position }); return null; } function App() { return ( ); } ``` See a full example [here](/examples/mapbox/draw-polygon). ## Signature ```js useControl( onCreate: ({map: MapRef, mapLib: mapboxgl}) => IControl, options?: { position?: ControlPosition; } ): T useControl( onCreate: ({map: MapRef, mapLib: mapboxgl}) => IControl, onRemove: ({map: MapRef, mapLib: mapboxgl}) => void, options?: { position?: ControlPosition; } ): T useControl( onCreate: ({map: MapRef, mapLib: mapboxgl}) => IControl, onAdd: ({map: MapRef, mapLib: mapboxgl}) => void, onRemove: ({map: MapRef, mapLib: mapboxgl}) => void, options?: { position?: ControlPosition; } ): T ``` The hook creates an [IControl](https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol) instance, adds it to the map when it's available, and removes it upon unmount. Parameters: - `onCreate`: (`{map: MapRef, mapLib: mapboxgl}`) => [IControl](./types.md#icontrol) - called to create an instance of the control. - `onAdd`: (`{map: MapRef, mapLib: mapboxgl}`) => void - called when the control has been added to the map. - `onRemove`: (`{map: MapRef, mapLib: mapboxgl}`) => void - called when the control is about to be removed from the map. - `options`: object + `position`: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' - control position relative to the map Returns: [IControl](./types.md#icontrol) - the control instance from `onCreate`. ## Source [use-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/use-control.ts) ================================================ FILE: docs/api-reference/mapbox/use-map.md ================================================ # useMap The `useMap` hook allows a component to reference the [Map](./map.md) that contains it. When used with [MapProvider](./map-provider.md), this hook can also reference maps that are rendered outside of the current map component's direct render tree. ```tsx import {Map, useMap} from 'react-map-gl/mapbox'; function Root() { return ( ); } function NavigateButton() { const {current: map} = useMap(); const onClick = () => { map.flyTo({center: [-122.4, 37.8]}); }; return ; } ``` When used with the [MapProvider](./map-provider.md), this hook can also reference maps that are rendered outside of the current component's direct render tree as long as both trees are part of the current ``. ```tsx import {MapProvider, Map, useMap} from 'react-map-gl/mapbox'; function Root() { // Note: `useMap` will not work in , only children of can use `useMap` return ( ); } function NavigateButton() { const {myMapA, myMapB} = useMap(); const onClick = () => { myMapA.flyTo({center: [-122.4, 37.8]}); myMapB.flyTo({center: [-74, 40.7]}); }; return ; } ``` See a full example [here](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/hook). ## Signature `useMap(): {current?: MapRef, [id: string]: MapRef}` The hook returns an object that contains all mounted maps under the closest `MapProvider`. The keys are each map's [id](./map.md#id) and the values are the [MapRef](./types.md#mapref). If the hook is used inside a decendent of a `Map` component, the returned object additionally contains a `current` field that references the containing map. ## Source [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-mapbox/src/components/use-map.tsx) ================================================ FILE: docs/api-reference/maplibre/attribution-control.md ================================================ # AttributionControl React component that wraps maplibre-gl's [AttributionControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/AttributionControl/) class. ```tsx import * as React from 'react'; import {Map, AttributionControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/AttributionControlOptions/) supported by the `AttributionControl` class, such as - `compact` - `customAttribution` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'bottom-right'` Placement of the control relative to the map. ## Source [attribution-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/attribution-control.ts) ================================================ FILE: docs/api-reference/maplibre/fullscreen-control.md ================================================ # FullscreenControl React component that wraps maplibre-gl's [FullscreenControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/FullscreenControl/) class. ```tsx import * as React from 'react'; import {Map, FullscreenControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. #### `containerId`: string {#containerid} Id of the DOM element which should be made full screen. By default, the map container element will be made full screen. #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [fullscreen-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/fullscreen-control.ts) ================================================ FILE: docs/api-reference/maplibre/geolocate-control.md ================================================ # GeolocateControl React component that wraps maplibre-gl's [GeolocateControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/GeolocateControl/) class. ```tsx import * as React from 'react'; import {Map, GeolocateControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Callbacks #### `onGeolocate`: (evt: [GeolocateResultEvent](./types.md#geolocateresultevent)) => void {#ongeolocate} Called on each Geolocation API position update that returned as success. #### `onError`: (evt: [GeolocateErrorEvent](./types.md#geolocateerrorevent)) => void {#onerror} Called on each Geolocation API position update that returned as an error. #### `onOutOfMaxBounds`: (evt: [GeolocateResultEvent](./types.md#geolocateresultevent)) => void {#onoutofmaxbounds} Called on each Geolocation API position update that returned as success but user position is out of map `maxBounds`. #### `onTrackUserLocationStart`: (evt: [GeolocateEvent](./types.md#geolocateevent)) => void {#ontrackuserlocationstart} Called when the GeolocateControl changes to the active lock state. #### `onTrackUserLocationEnd`: (evt: [GeolocateEvent](./types.md#geolocateevent)) => void {#ontrackuserlocationend} Called when the GeolocateControl changes to the background state. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/GeolocateControlOptions/) supported by the `GeolocateControl` class, such as - `positionOptions` - `fitBoundsOptions` - `trackUserLocation` - `showAccuracyCircle` - `showUserLocation` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'bottom-right'` Placement of the control relative to the map. ## Methods The underlying native `GeolocateControl` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useEffect} from 'react'; import {Map, GeolocateControl} from 'react-map-gl/maplibre'; import type maplibregl from 'maplibre-gl'; function App() { const geoControlRef = useRef(); useEffect(() => { // Activate as soon as the control is loaded geoControlRef.current?.trigger(); }, [geoControlRef.current]); return ; } ``` ## Source [geolocate-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/geolocate-control.ts) ================================================ FILE: docs/api-reference/maplibre/globe-control.md ================================================ # GlobeControl React component that wraps maplibre-gl's [GlobeControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/GlobeControl/) class. ```tsx import * as React from 'react'; import {Map, GlobeControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [globe-control.ts](https://github.com/visgl/react-map-gl/tree/9.0-release/modules/react-maplibre/src/components/globe-control.ts) ================================================ FILE: docs/api-reference/maplibre/layer.md ================================================ # Layer This component allows apps to create a [map layer](https://maplibre.org/maplibre-style-spec/layers/) using React. ```tsx import * as React from 'react'; import {Map, Layer} from 'react-map-gl/maplibre'; import type {FillLayer} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; const parkLayer: FillLayer = { id: 'landuse_park', type: 'fill', source: 'vector', 'source-layer': 'landuse', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#4E3FC8' } }; function App() { return ; } ``` ## Properties The props provided to this component should be conforming to the [Maplibre layer specification](https://maplibre.org/maplibre-style-spec/layers/). When props change *shallowly*, the component will perform style diffing to update the layer. Avoid defining constant objects/arrays inline may help performance. ### Identity Properties Once a `` is mounted, the following props should not change. If you add/remove multiple JSX layers dynamically, make sure you use React's [key prop](https://reactjs.org/docs/lists-and-keys.html#keys) to give each element a stable identity. #### `id`: string {#id} Unique identifier of the layer. If not provided, a default id will be assigned. #### `type`: string {#type} Required. Type of the layer. ### Options #### `beforeId`: string {#beforeid} The ID of an existing layer to insert this layer before. If this prop is omitted, the layer will be appended to the end of the layers array. This is useful when using dynamic layers with a map style from a URL. Note that layers are added by the order that they mount. They are *NOT* reordered later if their relative positions in the JSX tree change. If dynamic reordering is desired, you should manipulate `beforeId` for consistent behavior. #### `source`: string {#source} `source` is required by some layer types in the Mapbox style specification. If `` is used as the immediate child of a [Source](./source.md) component, this prop will be overwritten by the id of the parent source. If the `` component is not an immediate descendant of ``, e.g wrapped inside a helper component, source property needs to be provided same as the id of the `` component for the `` component to show. ## Source [layer.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/layer.ts) ================================================ FILE: docs/api-reference/maplibre/logo-control.md ================================================ # LogoControl React component that wraps maplibre-gl's [LogoControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/LogoControl/) class. ```tsx import * as React from 'react'; import {Map, LogoControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/LogoControlOptions/) supported by the `LogoControl` class, such as - `compact` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [logo-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/logo-control.ts) ================================================ FILE: docs/api-reference/maplibre/map-provider.md ================================================ # MapProvider A [Context.Provider](https://reactjs.org/docs/context.html#contextprovider) that facilitates map operations outside of the component that directly renders a [Map](./map.md). The component should wrap all nodes in which you may want to access the maps: ```tsx import {MapProvider} from 'react-map-gl/maplibre'; function Root() { return ( { // Application tree, somewhere one or more component(s) are rendered } ); } ``` See [useMap](./use-map.md) for more information. ## Source [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/use-map.tsx) ================================================ FILE: docs/api-reference/maplibre/map.md ================================================ # default (Map) React component that wraps maplibre-gl's [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) class. This is also the default export from `react-map-gl/maplibre`. ```tsx import * as React from 'react'; import {Map} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ( ); } ``` ## Properties Aside from the props listed below, the `Map` component supports all [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/) of the `Map` class constructor. Beware that this is not an exhaustive list of all props. Different base map libraries may offer different options and default values. When in doubt, refer to your base map library's documentation. ### Layout options #### `id`: string {#id} Map container id. #### `style`: CSSProperties {#style} Default: `{position: 'relative', width: '100%', height: '100%'}` Map container CSS. #### `cursor`: string {#cursor} Default: `'auto'` The current cursor [type](https://developer.mozilla.org/en-US/docs/Web/CSS/cursor). ### Styling options #### `light`: [Light](./types.md#light) {#light} Light properties of the style. Must conform to the [Light Style Specification](https://maplibre.org/maplibre-style-spec/light/). #### `mapStyle`: [MapStyle](./types.md#mapstyle) | string | Immutable {#mapstyle} Default: (empty style) The map's Maplibre style. This must be an a JSON object conforming to the schema described in the [MapLibre Style Specification](https://maplibre.org/maplibre-style-spec/), or a URL to such JSON. #### `projection`: string | [Projection](./types.md#projection) {#projection} Default: `'mercator'` The projection the map should be rendered in. See [Projection Specification](https://maplibre.org/maplibre-style-spec/projection/). #### `renderWorldCopies`: boolean {#renderworldcopies} Default: `true` If `true`, multiple copies of the world will be rendered, when zoomed out. #### `sky`: [Sky](./types.md#sky) {#sky} The sky property of the style. Must conform to the [Sky Style Specification](https://maplibre.org/maplibre-style-spec/sky/). #### `styleDiffing`: boolean {#stylediffing} Default: `true` Enable diffing when `mapStyle` changes. If `false`, force a 'full' update, removing the current style and building the given one instead of attempting a diff-based update. #### `terrain`: [Terrain](./types.md#terrain)|null {#terrain} Terrain property of the style. Must conform to the [Terrain Style Specification](https://maplibre.org/maplibre-style-spec/terrain/). If `null` is provided, removes terrain from the map. ### Camera options #### `initialViewState`: object {#initialviewstate} The initial view state of the map. If specified, `longitude`, `latitude`, `zoom` etc. in props are ignored when constructing the map. Only specify `initialViewState` if `Map` is being used as an **uncontrolled component**. See [state management](../../get-started/state-management.md) for examples. - `bounds`: [LngLatBoundsLike](./types.md#lnglatboundslike) - The initial bounds of the map. If specified, it overrides the `longitude`, `latitude` and `zoom` options. Default `null`. - `fitBoundsOptions` - An object to use only when setting the `bounds` option. Default `null`. + `fitBoundsOptions.offset`: [PointLike](./types.md#pointlike) + `fitBoundsOptions.minZoom`: number + `fitBoundsOptions.maxZoom`: number + `fitBoundsOptions.padding`: [PaddingOptions](./types.md#paddingoptions) - `longitude`: number - The initial longitude of the map center. Default `0`. - `latitude`: number - The initial latitude of the map center. Default `0`. - `zoom`: number - The initial zoom level. Default `0`. - `pitch`: number - The initial pitch (tilt) of the map. Default `0`. - `bearing`: number - The initial bearing (rotation) of the map. Default `0`. #### `longitude`: number {#longitude} The longitude of the map center. #### `latitude`: number {#latitude} The latitude of the map center. #### `zoom`: number {#zoom} The [zoom level](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/#zoom) of the map. #### `pitch`: number {#pitch} The initial [pitch](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/#pitch) (tilt) of the map, measured in degrees away from the plane of the screen (0-85). #### `bearing`: number {#bearing} The initial [bearing](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/#bearing) (rotation) of the map, measured in degrees counter-clockwise from north. #### `padding`: [PaddingOptions](./types.md#paddingoptions) {#padding} Default: `null` The padding in pixels around the viewport. #### `minZoom`: number {#minzoom} Default: `0` The minimum zoom level of the map (0-24). #### `maxZoom`: number {#maxzoom} Default: `22` The maximum zoom level of the map (0-24). #### `minPitch`: number {#minpitch} Default: `0` The minimum pitch of the map (0-85). #### `maxPitch`: number {#maxpitch} Default: `60` The maximum pitch of the map (0-85). #### `maxBounds`: [LngLatBoundsLike](./types.md#lnglatboundslike) {#maxbounds} Default: `null` If set, the map is constrained to the given bounds. ### Input handler options #### `boxZoom`: boolean {#boxzoom} Default: `true` If `true`, the "box zoom" interaction is enabled. See [BoxZoomHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/BoxZoomHandler/). #### `doubleClickZoom`: boolean {#doubleclickzoom} Default: `true` If `true`, the "double click to zoom" interaction is enabled. See [DoubleClickZoomHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/DoubleClickZoomHandler/). #### `dragRotate`: boolean {#dragrotate} Default: `true` If `true`, the "drag to rotate" interaction is enabled. See [DragRotateHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/DragRotateHandler/). #### `dragPan`: boolean | Object {#dragpan} Default: `true` If `true`, the "drag to pan" interaction is enabled. Optionally accept an object value that is the options to [DragPanHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/DragPanHandler/). #### `keyboard`: boolean {#keyboard} Default: `true` If `true`, keyboard shortcuts are enabled. See [KeyboardHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/KeyboardHandler/). #### `scrollZoom`: boolean | Object {#scrollzoom} Default: `true` If `true`, the "scroll to zoom" interaction is enabled. Optionally accept an object value that is the options to [ScrollZoomHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/ScrollZoomHandler/). #### `touchPitch`: boolean | Object {#touchpitch} Default: `true` If `true`, the "drag to pitch" interaction is enabled. Optionally accept an object value that is the options to [TwoFingersTouchPitchHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/TwoFingersTouchPitchHandler/). #### `touchZoomRotate`: boolean | Object {#touchzoomrotate} Default: `true` If `true`, the "pinch to rotate and zoom" interaction is enabled. Optionally accept an object value that is the options to [TwoFingersTouchZoomRotateHandler](https://maplibre.org/maplibre-gl-js/docs/API/classes/TwoFingersTouchZoomRotateHandler/). #### `interactiveLayerIds`: string[] {#interactivelayerids} Default: `null` The id(s) of style layer(s). If specified, pointer event (`mousemove`, `click` etc.) listeners will be triggered only if its location is within a visible feature in these layers, and the event will have a `features` property containing an array of the matching features. If not specified, pointer event listeners will be triggered by a corresponding event happening anywhere on the map, and the event will not have a `features` property. See the [Callbacks](#callbacks) section for affected events. ### Callbacks #### `onResize`: (event: [MapEvent](./types.md#mapevent)) => void {#onresize} Called when the map has been resized. #### `onLoad`: (event: [MapEvent](./types.md#mapevent)) => void {#onload} Called after all necessary resources have been downloaded and the first visually complete rendering of the map has occurred. #### `onRender`: (event: [MapEvent](./types.md#mapevent))) => void {#onrender} Called whenever the map is drawn to the screen. #### `onIdle`: (event: [MapEvent](./types.md#mapevent))) => void {#onidle} Called after the last frame rendered before the map enters an "idle" state: - No camera transitions are in progress - All currently requested tiles have loaded - All fade/transition animations have completed #### `onRemove`: (event: [MapEvent](./types.md#mapevent))) => void {#onremove} Called when the map has been removed. #### `onError`: (event: [ErrorEvent](./types.md#errorevent)) => void {#onerror} Default: `evt => console.error(evt.error)` Called when an error occurs. #### `onMouseDown`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmousedown} Called when a pointing device (usually a mouse) is pressed within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onMouseUp`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseup} Called when a pointing device (usually a mouse) is released within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onMouseOver`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseover} Called when a pointing device (usually a mouse) is moved within the map. As you move the cursor across a web page containing a map, the event will fire each time it enters the map or any child elements. #### `onMouseEnter`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseenter} Called when a pointing device (usually a mouse) enters a visible portion of the layer(s) specified by `interactiveLayerIds` from outside that layer or outside the map canvas. #### `onMouseMove`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmousemove} Called when a pointing device (usually a mouse) is moved while the cursor is inside the map. As you move the cursor across the map, the event will fire every time the cursor changes position within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onMouseLeave`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseleave} Called when a pointing device (usually a mouse) leaves a visible portion of the layer(s) specified by `interactiveLayerIds` or moves from the layer to outside the map canvas. #### `onMouseOut`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onmouseout} Called when a point device (usually a mouse) leaves the map's canvas. #### `onClick`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#onclick} Called when a pointing device (usually a mouse) is pressed and released at the same point on the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onDblClick`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#ondblclick} Called when a pointing device (usually a mouse) is pressed and released twice at the same point on the map in rapid succession. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onContextMenu`: (event: [MapLayerMouseEvent](./types.md#maplayermouseevent)) => void {#oncontextmenu} Called when the right button of the mouse is clicked or the context menu key is pressed within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onWheel`: (event: [MapWheelEvent](./types.md#mapwheelevent)) => void {#onwheel} Called when a wheel event occurs within the map. #### `onTouchStart`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchstart} Called when a `touchstart` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onTouchEnd`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchend} Called when a `touchend` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onTouchMove`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchmove} Called when a `touchmove` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onTouchCancel`: (event: [MapLayerTouchEvent](./types.md#maplayertouchevent)) => void {#ontouchcancel} Called when a `touchcancel` event occurs within the map. If `interactiveLayerIds` is specified, the event will contain an additional `features` field that contains features under the cursor from the specified layer. #### `onMoveStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmovestart} Called just before the map begins a transition from one view to another. #### `onMove`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmove} Called repeatedly during an animated transition from one view to another. When `Map` is used as a controlled component, `event.viewState` reflects the view state that the camera "proposes" to move to, as a result of either user interaction or methods such as [flyTo](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#flyto). The camera does not actually change until the application updates the view state props (`longitude`, `latitude`, `zoom` etc.). See [state management](../../get-started/state-management.md) for examples. #### `onMoveEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onmoveend} Called just after the map completes a transition from one view to another. #### `onDragStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondragstart} Called when a "drag to pan" interaction starts. #### `onDrag`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondrag} Called repeatedly during a "drag to pan" interaction. #### `onDragEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#ondragend} Called when a "drag to pan" interaction ends. #### `onZoomStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoomstart} Called just before the map begins a transition from one zoom level to another. #### `onZoom`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoom} Called repeatedly during an animated transition from one zoom level to another. When `Map` is used as a controlled component, `event.viewState.zoom` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#flyto). The camera does not actually change until the application updates the `zoom` prop. #### `onZoomEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onzoomend} Called just after the map completes a transition from one zoom level to another. #### `onRotateStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotatestart} Called just before the map begins a transition from one bearing (rotation) to another. #### `onRotate`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotate} Called repeatedly during an animated transition from one bearing (rotation) to another. When `Map` is used as a controlled component, `event.viewState.bearing` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#flyto). The camera does not actually change until the application updates the `bearing` prop. #### `onRotateEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onrotateend} Called just after the map completes a transition from one bearing (rotation) to another. #### `onPitchStart`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitchstart} Called just before the map begins a transition from one pitch (tilt) to another. #### `onPitch`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitch} Called repeatedly during an animated transition from one pitch (tilt) to another. When `Map` is used as a controlled component, `event.viewState.pitch` reflects the zoom that the camera "proposes" to change to, as a result of either user interaction or methods such as [flyTo](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#flyto). The camera does not actually change until the application updates the `pitch` prop. #### `onPitchEnd`: (event: [ViewStateChangeEvent](./types.md#viewstatechangeevent)) => void {#onpitchend} Called just after the map completes a transition from one pitch (tilt) to another. #### `onBoxZoomStart`: (event: [MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomstart} Called when a "box zoom" interaction starts. #### `onBoxZoomEnd`: (event: [MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomend} Called when a "box zoom" interaction ends. #### `onBoxZoomCancel`: (event:[MapBoxZoomEvent](./types.md#mapboxzoomevent)) => void {#onboxzoomcancel} Called when the user cancels a "box zoom" interaction, or when the bounding box does not meet the minimum size threshold. #### `onData`: (event: [MapStyleDataEvent](./types.md#mapstyledataevent) | [MapSourceDataEvent](./types.md#mapsourcedataevent)) => void {#ondata} Called when any map data loads or changes. See [MapDataEvent](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapDataEvent/) for more information. #### `onStyleData`: (event: [MapStyleDataEvent](./types.md#mapstyledataevent)) => void {#onstyledata} Called when the map's style loads or changes. See [MapDataEvent](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapDataEvent/) for more information. #### `onSourceData`: (event: [MapSourceDataEvent](./types.md#mapsourcedataevent)) => void {#onsourcedata} Called when one of the map's sources loads or changes, including if a tile belonging to a source loads or changes. See [MapDataEvent](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapDataEvent/) for more information. ### Other options The following props, along with any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapOptions/) of the `Map` class not listed above, can be specified to construct the underlying `Map` instance. Note: props in this section are not reactive. They are only used once when the Map instance is constructed. #### `mapLib`: any {#maplib} Default: - `import('maplibre-gl')` Specify the underlying base map library for the Map component. The value can be provided with several options: By module import (and embedding in the final bundle): ```tsx import * as React from 'react'; import {Map} from 'react-map-gl/maplibre'; import maplibregl from 'maplibre-gl'; function App() { return ; } ``` By dynamic import (thus enable bundle splitting): ```tsx import * as React from 'react'; import {Map} from 'react-map-gl/maplibre'; function App() { return ; } ``` Or to load a pre-bundled version of the library: ```html title="index.html" ``` ```tsx title="app.tsx" import * as React from 'react'; import {Map} from 'react-map-gl/maplibre'; function App() { return ; } ``` #### `maxParallelImageRequests`: number {#maxparallelimagerequests} Default: `16` The maximum number of images (raster tiles, sprites, icons) to load in parallel. #### `reuseMaps`: boolean {#reusemaps} Default: `false` By default, every time a map component is unmounted, all internal resources associated with the underlying `Map` instance are released. If the map gets mounted again, a new `Map` instance is constructed. If `reuseMaps` is set to `true`, when a map component is unmounted, the underlying `Map` instance is retained in memory. The next time a map component gets mounted, the saved instance is reused. This behavior may be desirable if an application frequently mounts/unmounts map(s), for example in a tabbed or collapsable UI, and wants to avoid recreating the Map and its data cache triggered by initialization. Note that since some map options cannot be modified after initialization, when reusing maps, only the reactive props and `initialViewState` of the new component are respected. #### `RTLTextPlugin`: string | object {#rtltextplugin} - `pluginUrl`: `string` URL to the plugin JS file. - `lazy`: `boolean` When true, the plugin is only loaded when the map first encounters Hebrew or Arabic text. Default `true`. Sets the map's RTL text plugin via [setRTLTextPlugin](https://maplibre.org/maplibre-gl-js/docs/API/functions/setRTLTextPlugin/). Can be used with [mapbox-gl-rtl-text](https://github.com/mapbox/mapbox-gl-rtl-text). Necessary for supporting the Arabic and Hebrew languages, which are written right-to-left. #### `workerCount`: number {#workercount} Default: `2` The number of web workers instantiated on a page with maplibre-gl maps. #### `workerUrl`: string {#workerurl} Provides an interface for loading maplibre-gl's WebWorker bundle from a self-hosted URL. This is useful if your site needs to operate in a strict CSP (Content Security Policy) environment wherein you are not allowed to load JavaScript code from a Blob URL, which is default behavior. ## Methods Imperative methods are accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) or the [useMap](./use-map.md) hook. ```tsx import * as React from 'react'; import {useRef, useCallback} from 'react'; import {Map} from 'react-map-gl/maplibre'; import type {MapRef} from 'react-map-gl/maplibre'; function App() { const mapRef = useRef(); const onMapLoad = useCallback(() => { mapRef.current.on('move', () => { // do something }); }, []); return ; } ``` The [MapRef](./types.md#mapref) object exposes [Map methods](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/#methods) that **are safe to call without breaking the React bindings**. For example, `setStyle()` is hidden from the ref object, because the style is supposed to be changed by updating the `mapStyle` prop. Calling the method directly may cause the the React prop to mismatch with the underlying state, and lead to unexpected behaviors. You can still access the hidden members via `getMap()`: #### `getMap()` {#getmap} Returns the native [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) instance associated with this component. ## Source [map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/map.tsx) ================================================ FILE: docs/api-reference/maplibre/marker.md ================================================ # Marker React component that wraps maplibre-gl's [Marker](https://maplibre.org/maplibre-gl-js/docs/API/classes/Marker/) class. ```tsx import * as React from 'react'; import {Map, Marker} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` If `Marker` is mounted with child components, then its content will be rendered to the specified location. If it is mounted with no content, then a default marker will be used. ## Properties ### Reactive Properties #### `draggable`: boolean {#draggable} Default: `false` If `true`, the marker is able to be dragged to a new position on the map. #### `latitude`: number {#latitude} Required. The latitude of the anchor location. #### `longitude`: number {#longitude} Required. The longitude of the anchor location. #### `offset`: [PointLike](./types.md#pointlike) {#offset} Default: `null` The offset in pixels as a [PointLike](./types.md#pointlike) object to apply relative to the element's center. Negatives indicate left and up. #### `pitchAlignment`: 'map' | 'viewport' | 'auto' {#pitchalignment} Default: `'auto'` - `map` aligns the `Marker` to the plane of the map. - `viewport` aligns the `Marker` to the plane of the viewport. - `auto` automatically matches the value of `rotationAlignment`. #### `popup`: Popup | null {#popup} An instance of the [Popup](https://maplibre.org/maplibre-gl-js/docs/API/classes/Popup/) class to attach to this marker. If undefined or null, any popup set on this Marker instance is unset. #### `rotation`: number {#rotation} Default: `0` The rotation angle of the marker in degrees, relative to its `rotationAlignment` setting. A positive value will rotate the marker clockwise. #### `rotationAlignment`: 'map' | 'viewport' | 'auto' {#rotationalignment} Default: `'auto'` - `map` aligns the `Marker`'s rotation relative to the map, maintaining a bearing as the map rotates. - `viewport` aligns the `Marker`'s rotation relative to the viewport, agnostic to map rotations. - `auto` is equivalent to `viewport`. #### `style`: CSSProperties {#style} CSS style override that applies to the marker's container. ### Callbacks #### `onClick`: (evt: [MapEvent](./types.md#mapevent)) => void {#onclick} Called when the marker is clicked on. #### `onDragStart`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondragstart} Called when dragging starts, if `draggable` is `true`. #### `onDrag`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondrag} Called while dragging, if `draggable` is `true`. #### `onDragEnd`: (evt: [MarkerDragEvent](./types.md#markerdragevent)) => void {#ondragend} Called when dragging ends, if `draggable` is `true`. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MarkerOptions/) supported by the `Marker` class, such as - `anchor` - `color` - `scale` - `clickTolerance` ## Methods The underlying native `Marker` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useMemo, useCallback} from 'react'; import {Map, Marker} from 'react-map-gl/maplibre'; import maplibregl from 'maplibre-gl'; function App() { const markerRef = useRef(); const popup = useMemo(() => { return maplibregl.Popup().setText('Hello world!'); }, []) const togglePopup = useCallback(() => { markerRef.current?.togglePopup(); }, []); return <> ; } ``` ## Source [marker.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/marker.ts) ================================================ FILE: docs/api-reference/maplibre/navigation-control.md ================================================ # NavigationControl React component that wraps maplibre-gl's [NavigationControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/NavigationControl/) class. ```tsx import * as React from 'react'; import {Map, NavigationControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/NavigationControlOptions/) supported by the `NavigationControl` class, such as - `showCompass` - `showZoom` - `visualizePitch` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [navigation-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/navigation-control.ts) ================================================ FILE: docs/api-reference/maplibre/popup.md ================================================ # Popup React component that wraps maplibre-gl's [Popup](https://maplibre.org/maplibre-gl-js/docs/API/classes/Popup/) class. ```tsx import * as React from 'react'; import {useState} from 'react'; import {Map, Popup} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { const [showPopup, setShowPopup] = useState(true); return {showPopup && ( setShowPopup(false)}> You are here )} ; } ``` ## Properties ### Reactive Properties #### `anchor`: 'center' | 'left' | 'right' | 'top' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | undefined {#anchor} A string indicating the part of the popup that should be positioned closest to the coordinate, set via `longitude` and `latitude`. If unset, the anchor will be dynamically set to ensure the popup falls within the map container with a preference for `'bottom'`. #### `className`: string {#classname} Space-separated CSS class names to add to popup container. #### `offset`: number | [PointLike](./types.md#pointlike) | Record\ {#offset} Default: `null` A pixel offset applied to the popup's location specified as: - a single number specifying a distance from the popup's location - a PointLike specifying a constant offset - an object of Points specifing an offset for each anchor position. Negative offsets indicate left and up. #### `maxWidth`: string {#maxwidth} Default: `240px` A string that sets the CSS property of the popup's maximum width. #### `style`: CSSProperties {#style} CSS style override that applies to the popup's container. ### Callbacks #### `onOpen`: (evt: [PopupEvent](./types.md#popupevent)) => void {#onopen} Called when the popup is opened. #### `onClose`: (evt: [PopupEvent](./types.md#popupevent)) => void {#onclose} Called when the popup is closed by the user clicking on the close button or outside (if `closeOnClick: true`). ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/PopupOptions/) supported by the `Popup` class, such as - `closeButton` - `closeOnClick` - `closeOnMove` - `focusAfterOpen` ## Methods The underlying native `Popup` instance is accessible via a [React ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) hook. You may use it to call any imperative methods: ```tsx import * as React from 'react'; import {useRef, useEffect} from 'react'; import {Map, Popup} from 'react-map-gl/maplibre'; import maplibregl from 'maplibre-gl'; function App() { const popupRef = useRef(); useEffect(() => { popupRef.current?.trackPointer(); }, [popupRef.current]) return Tooltip ; } ``` ## Source [popup.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/popup.ts) ================================================ FILE: docs/api-reference/maplibre/scale-control.md ================================================ # ScaleControl React component that wraps maplibre-gl's [ScaleControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/ScaleControl/) class. ```tsx import * as React from 'react'; import {Map, ScaleControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ; } ``` ## Properties ### Reactive Properties #### `maxWidth`: string {#maxwidth} Default: `100` The maximum length of the scale control in pixels. #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. #### `unit`: 'imperial' | 'metric' | 'nautical' {#unit} Default: `'metric'` Unit of the distance. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [scale-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/scale-control.ts) ================================================ FILE: docs/api-reference/maplibre/source.md ================================================ # Source This component allows apps to create a [map source](https://maplibre.org/maplibre-style-spec/sources/) using React. It may contain [Layer](./layer.md) components as children. ```tsx import * as React from 'react'; import {Map, Source, Layer} from 'react-map-gl/maplibre'; import type {CircleLayer} from 'react-map-gl/maplibre'; import type {FeatureCollection} from 'geojson'; import 'maplibre-gl/dist/maplibre-gl.css'; const geojson: FeatureCollection = { type: 'FeatureCollection', features: [ {type: 'Feature', geometry: {type: 'Point', coordinates: [-122.4, 37.8]}} ] }; const layerStyle: CircleLayer = { id: 'point', type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; function App() { return ; } ``` ## Properties The props provided to this component should be conforming to the [Mapbox source specification](https://maplibre.org/maplibre-style-spec/sources/) or [CanvasSourceSpecification](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/CanvasSourceSpecification/). When props change _shallowly_, the component will attempt to update the source. Do not define objects/arrays inline to avoid perf hit. Once a `` is mounted, the following props should not change. If add/remove multiple JSX sources dynamically, make sure you use React's [key prop](https://reactjs.org/docs/lists-and-keys.html#keys) to give each element a stable identity. #### `id`: string {#id} Unique identifier of the source. If not provided, a default id will be assigned. #### `type`: string {#type} Required. Type of the source. ## Source [source.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/source.ts) ================================================ FILE: docs/api-reference/maplibre/terrain-control.md ================================================ # TerrainControl React component that wraps maplibre-gl's [TerrainControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/TerrainControl/) class. ```tsx import * as React from 'react'; import {Map, MapStyle, TerrainControl} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; // https://maplibre.org/maplibre-gl-js/docs/examples/3d-terrain/ const MAP_STYLE: MapStyle = { version: 8, sources: { osm: { type: 'raster', tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'], tileSize: 256, attribution: '© OpenStreetMap Contributors', maxzoom: 19 }, terrainSource: { type: 'raster-dem', url: 'https://demotiles.maplibre.org/terrain-tiles/tiles.json', tileSize: 256 } }, layers: [ { id: 'osm', type: 'raster', source: 'osm' } ], terrain: { source: 'terrainSource', exaggeration: 1 }, sky: {} }; function App() { return ; } ``` ## Properties ### Reactive Properties #### `style`: CSSProperties {#style} CSS style override that applies to the control's container. ### Other Properties The properties in this section are not reactive. They are only used when the component first mounts. Any [options](https://maplibre.org/maplibre-style-spec/terrain/) supported by the `TerrainControl` class, such as - `source` - `exageration` Plus the following: #### `position`: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' {#position} Default: `'top-right'` Placement of the control relative to the map. ## Source [terrain-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/terrain-control.ts) ================================================ FILE: docs/api-reference/maplibre/types.md ================================================ # Types The following types can be imported from `react-map-gl/maplibre` when using TypeScript. ## Components #### IControl A [custom control implementation](https://maplibre.org/maplibre-gl-js/docs/API/interfaces/IControl/). #### CustomLayerInterface A [custom layer implementation](https://maplibre.org/maplibre-gl-js/docs/API/interfaces/CustomLayerInterface/). #### MapRef Instance [ref](https://reactjs.org/docs/refs-and-the-dom.html#creating-refs) of a `Map` component. See [Map documentation](./map.md#methods) for details. ## Styling #### StyleSpecification An object conforming to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/). #### SkySpecification An object conforming to the [Sky Style Specification](https://maplibre.org/maplibre-style-spec/sky/). #### LightSpecification An object conforming to the [Light Style Specification](https://maplibre.org/maplibre-style-spec/light/). #### TerrainSpecification An object conforming to the [Terrain Style Specification](https://maplibre.org/maplibre-style-spec/terrain/). #### ProjectionSpecification An object conforming to the [Projection Style Specification](https://maplibre.org/maplibre-style-spec/projection/). #### BackgroundLayerSpecification A JSON object that defines a `background` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#background). #### CircleLayerSpecification A JSON object that defines a `circle` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers//#circle). #### FillExtrusionLayerSpecification A JSON object that defines a `fill-extrusion` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#fill-extrusion). #### FillLayerSpecification A JSON object that defines a `fill` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#fill). #### HeatmapLayerSpecification A JSON object that defines a `heatmap` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#heatmap). #### HillshadeLayerSpecification A JSON object that defines a `hillshade` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#hillshade). #### LineLayerSpecification A JSON object that defines a `line` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#line). #### RasterLayerSpecification A JSON object that defines a `raster` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#raster). #### SymbolLayerSpecification A JSON object that defines a `symbol` layer according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/layers/#symbol). #### GeoJSONSourceSpecification A JSON object that defines a `geojson` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#geojson). #### VideoSourceSpecification A JSON object that defines a `video` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#video). #### ImageSourceSpecification A JSON object that defines a `image` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#image). #### VectorSourceSpecification A JSON object that defines a `vector` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#vector). #### RasterSourceSpecification A JSON object that defines a `raster` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#raster). #### RasterDEMSourceSpecification A JSON object that defines a `raster-dem` source according to the [Maplibre Style Specification](https://maplibre.org/maplibre-style-spec/sources/#raster-dem). #### CanvasSourceSpecification A JSON object that defines a `canvas` source type. See [CanvasSourceSpecification](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/CanvasSourceSpecification/). ## Configurations #### ControlPosition One of `'top-right'`, `'top-left'`, `'bottom-right'` and `'bottom-left'`. #### PaddingOptions An object with the following fields: - `left`: number - in pixels. - `top`: number - in pixels. - `right`: number - in pixels. - `bottom`: number - in pixels. ## Data Types #### LngLat A Maplibre [LngLat](https://maplibre.org/maplibre-gl-js/docs/API/classes/LngLat/) object. #### LngLatLike A Maplibre [LngLatLike](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/LngLatLike/) object. #### LngLatBounds A Maplibre [LngLatBounds](https://maplibre.org/maplibre-gl-js/docs/API/classes/LngLatBounds/) object. #### LngLatBoundsLike A Maplibre [LngLatBoundsLike](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/LngLatBoundsLike/) object. #### Point A Maplibre [Point](https://github.com/mapbox/point-geometry) object. #### PointLike A Maplibre [PointLike](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/PointLike/) object. #### MapGeoJSONFeature A [GeoJSON](http://geojson.org/) feature that also contains the following library-specific fields: - `layer`: Layer - `source`: string - `sourceLayer`: string - `state`: `{ [key: string]: any }` #### ViewState An object with the following fields: - `longitude`: number - The longitude of the map center. - `latitude`: number - The latitude of the map center. - `zoom`: number - The zoom level. - `pitch`: number - The pitch (tilt) of the map, in degrees. - `bearing`: number - The bearing (rotation) of the map, in degrees. ## Events #### MapEvent An object with the following fields: - `type`: string - Event type - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `originalEvent?`: [Event](https://developer.mozilla.org/en-US/docs/Web/API/Event) #### MapLayerMouseEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `originalEvent?`: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) - `point`: [Point](#point) - `lngLat`: [LngLat](#lnglat) - `preventDefault`: () => void - `defaultPrevented`: boolean - `features?`: [MapGeoJSONFeature](#mapgeojsonfeature)[] #### MapWheelEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `originalEvent?`: [WheelEvent](https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent) - `preventDefault`: () => void - `defaultPrevented`: boolean #### MapLayerTouchEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `originalEvent?`: [TouchEvent](https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent) - `point`: [Point](#point) - `lngLat`: [LngLat](#lnglat) - `points`: [Point](#point)[] - `lngLats`: [LngLat](#lnglat)[] - `preventDefault`: () => void - `defaultPrevented`: boolean - `features?`: [MapGeoJSONFeature](#mapgeojsonfeature)[] #### ViewStateChangeEvent An object with the following fields: - `type`: string - Event type - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `viewState`: [ViewState](#viewstate) - the next view state that the camera wants to change to based on user input or transition. #### MapBoxZoomEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `originalEvent?`: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) - `boxZoomBounds`: [LngLatBounds](#lnglatbounds) #### MapStyleDataEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `dataType`: 'style' #### MapSourceDataEvent An object with the following fields: - `type`: string - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `dataType`: 'source' - `isSourceLoaded`: boolean - `source`: string - `sourceId`: string - `sourceDataType`: 'metadata' | 'content' - `tile`: any - `coord`: Coordinate See [MapDataEvent](https://maplibre.org/maplibre-gl-js/docs/API/type-aliases/MapDataEvent/). #### ErrorEvent An object with the following fields: - `type`: 'error' - `target`: [Map](https://maplibre.org/maplibre-gl-js/docs/API/classes/Map/) - `error`: [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) #### GeolocateEvent An object with the following fields: - `type`: string - `target`: [GeolocateControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/GeolocateControl/) #### GeolocateResultEvent An object with the following fields: - `type`: string - `target`: [GeolocateControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/GeolocateControl/) - `coords`: [GeolocationCoordinates](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationCoordinates) - the current location. - `timestamp`: number - the time at which the location was retrieved. #### GeolocateErrorEvent An object with the following fields: - `type`: string - `target`: [GeolocateControl](https://maplibre.org/maplibre-gl-js/docs/API/classes/GeolocateControl/) - `code`: PERMISSION_DENIED | POSITION_UNAVAILABLE | TIMEOUT - see [GeolocationPositionError](https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError) - `message`: string - the details of the error. Specifications note that this is primarily intended for debugging use and not to be shown directly in a user interface. #### MarkerEvent An object with the following fields: - `type`: string - `target`: [Marker](https://maplibre.org/maplibre-gl-js/docs/API/classes/Marker/) #### MarkerDragEvent An object with the following fields: - `type`: string - `target`: [Marker](https://maplibre.org/maplibre-gl-js/docs/API/classes/Marker/) - `lngLat`: [LngLat](#lnglat) - the new location of the marker #### PopupEvent An object with the following fields: - `type`: string - `target`: [Popup](https://maplibre.org/maplibre-gl-js/docs/API/classes/Popup/) ================================================ FILE: docs/api-reference/maplibre/use-control.md ================================================ # useControl The `useControl` hook is used to create React wrappers for custom map controls. ```tsx import MapboxDraw from '@mapbox/mapbox-gl-draw'; import {Map, useControl} from 'react-map-gl/maplibre'; function DrawControl(props: DrawControlProps) { useControl(() => new MapboxDraw(props), { position: props.position }); return null; } function App() { return ( ); } ``` See a full example [here](/examples/maplibre/draw-polygon). ## Signature ```js useControl( onCreate: ({map: MapRef, mapLib: maplibregl}) => IControl, options?: { position?: ControlPosition; } ): T useControl( onCreate: ({map: MapRef, mapLib: maplibregl}) => IControl, onRemove: ({map: MapRef, mapLib: maplibregl}) => void, options?: { position?: ControlPosition; } ): T useControl( onCreate: ({map: MapRef, mapLib: maplibregl}) => IControl, onAdd: ({map: MapRef, mapLib: maplibregl}) => void, onRemove: ({map: MapRef, mapLib: maplibregl}) => void, options?: { position?: ControlPosition; } ): T ``` The hook creates an [IControl](https://maplibre.org/maplibre-gl-js/docs/API/interfaces/IControl/) instance, adds it to the map when it's available, and removes it upon unmount. Parameters: - `onCreate`: `({map: MapRef, mapLib: maplibregl}) => IControl` - called to create an instance of the control. - `onAdd`: `({map: MapRef, mapLib: maplibregl}) => void` - called when the control has been added to the map. - `onRemove`: `({map: MapRef, mapLib: maplibregl}) => void` - called when the control is about to be removed from the map. - `options`: object + `position`: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' - control position relative to the map Returns: [IControl](./types.md#icontrol) - the control instance from `onCreate`. ## Source [use-control.ts](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/use-control.ts) ================================================ FILE: docs/api-reference/maplibre/use-map.md ================================================ # useMap The `useMap` hook allows a custom component to reference the [Map](./map.md) that contains it. ```tsx import {Map, useMap} from 'react-map-gl/maplibre'; function Root() { return ( ); } function NavigateButton() { const {current: map} = useMap(); const onClick = () => { map.flyTo({center: [-122.4, 37.8]}); }; return ; } ``` When used with the [MapProvider](./map-provider.md), this hook can also reference maps that are rendered outside of the current component's direct render tree. ```tsx import {MapProvider, Map, useMap} from 'react-map-gl/maplibre'; function Root() { return ( ); } function NavigateButton() { const {myMapA, myMapB} = useMap(); const onClick = () => { myMapA.flyTo({center: [-122.4, 37.8]}); myMapB.flyTo({center: [-74, 40.7]}); }; return ; } ``` See a full example [here](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/hook). ## Signature `useMap(): {current?: MapRef, [id: string]: MapRef}` The hook returns an object that contains all mounted maps under the closest `MapProvider`. The keys are each map's [id](./map.md#id) and the values are the [MapRef](./types.md#mapref). If the hook is used inside a decendent of a `Map` component, the returned object also contains a `current` field that references the containing map. ## Source [use-map.tsx](https://github.com/visgl/react-map-gl/tree/8.0-release/modules/react-maplibre/src/components/use-map.tsx) ================================================ FILE: docs/get-started/adding-custom-data.md ================================================ # Adding Custom Data ## Native Mapbox Layers You can inject data and mapbox native layers using the [Source](../api-reference/mapbox/source.md) and [Layer](../api-reference/mapbox/layer.md) components: ```tsx import * as React from 'react'; import Map, {Source, Layer} from 'react-map-gl/maplibre'; import type {CircleLayer} from 'react-map-gl/maplibre'; import type {FeatureCollection} from 'geojson'; const geojson: FeatureCollection = { type: 'FeatureCollection', features: [ { type: 'Feature', geometry: { type: 'Point', coordinates: [-122.4, 37.8] }, properties: {title: '915 Front Street, San Francisco, California'} } ] }; const layerStyle: CircleLayer = { id: 'point', type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; function App() { return ( ); } ``` For details about data sources and layer configuration, check out the [Mapbox style specification](https://www.mapbox.com/mapbox-gl-js/style-spec). For dynamically updating data sources and layers, check out the [GeoJSON](https://visgl.github.io/react-map-gl/examples/maplibre/geojson) and [GeoJSON animation](http://visgl.github.io/react-map-gl/examples/maplibre/geojson-animation) examples. ## Custom Overlays You can implement a custom HTML or SVG overlay on top of the map that redraws whenever the camera changes. By calling `map.project()` you can adjust the DOM or CSS properties so that the customly-drawn features are always aligned with the map. See a full example [here](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/maplibre/custom-overlay). ## Other vis.gl Libraries For more feature rich and performant data visualization overlay use cases, you may consider using other visualization libraries. react-map-gl is part of the [vis.gl](https://www.github.com/visgl) ecosystem, a suite of high-performance data visualization tools for the Web. - [deck.gl](https://deck.gl) - WebGL-powered framework for the visualization of large datasets. - [loaders.gl](https://loaders.gl) - loaders for file formats focused on visualization of big data, including point clouds, 3D geometries, images, geospatial formats as well as tabular data. - [nebula.gl](https://nebula.gl) - 3D-enabled GeoJSON editing based on deck.gl and React. ================================================ FILE: docs/get-started/get-started.md ================================================ # Get Started You may find complete project setups in [get-started examples](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started). ## Installation Using `react-map-gl` requires `node >= 12` and `react >= 16.3`. import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ```bash npm install react-map-gl mapbox-gl @types/mapbox-gl ``` ```bash npm install react-map-gl maplibre-gl ``` ## Example ```tsx title="app.tsx" import * as React from 'react'; import Map from 'react-map-gl/mapbox'; // If using with mapbox-gl v1: // import Map from 'react-map-gl/mapbox-legacy'; import 'mapbox-gl/dist/mapbox-gl.css'; function App() { return ( ); } ``` See [about Mapbox tokens](./mapbox-tokens.md) for alternatives to providing a Mapbox token. ```tsx title="app.tsx" import * as React from 'react'; import Map from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function App() { return ( ); } ``` ## Styling The base map library requires its stylesheet be included at all times. The marker, popup and navigation components in react-map-gl also need the stylesheet to work properly. The above example code imports the CSS file directly into the app. Most bundlers support this syntax out-of-the-box or with an official plugin. Alternatively, you may add the stylesheet to the head of your page: ```html title="index.html" ``` Find out your mapbox version by running `yarn list mapbox-gl` or `npm ls mapbox-gl`. ```html title="index.html" ``` Find out your maplibre version by running `yarn list maplibre-gl` or `npm ls maplibre-gl`. ================================================ FILE: docs/get-started/mapbox-tokens.md ================================================ # About Mapbox Tokens `react-map-gl` itself is open source and free. It provides a React wrapper for `mapbox-gl`, `maplibre-gl` or compatible projects. Depending on which base map library you use, you may need a Mapbox token. You will need a Mapbox token if you use: - [mapbox-gl@>=2.0.0](https://github.com/mapbox/mapbox-gl-js/releases/tag/v2.0.0) - requires a mapbox access token in order to access the map renderer, and generates billable events regardlesss of whether you are displaying your own maps. - `mapbox-gl@1.x` - requires an access token only if you load the map styles and tiles from Mapbox's data service. See "Display Maps Without A Mapbox Token" section below for using non-Mapbox tiles. To get a Mapbox token, you will need to register on [the Mapbox website](https://www.mapbox.com). The token will be used to identify you and start serving up map tiles. The service is free until a certain level of traffic is exceeded. There are several ways to provide a token to your app, as showcased in some of the example folders: * Provide a `mapboxAccessToken` prop to the map component * Set the `MapboxAccessToken` environment variable (or set `REACT_APP_MAPBOX_ACCESS_TOKEN` if you are using Create React App) * Provide it in the URL, e.g `?access_token=TOKEN` We recommend using an environment variable to minimize leaking risks. See [securing Mapbox token](./tips-and-tricks.md#securing-mapbox-token) for examples. ## Display Maps Without A Mapbox Token It is possible to use the map component without the Mapbox service, if you use another tile source (for example, if you host your own map tiles). Note that this is no longer allowed using `mapbox-gl` v2.0 and above. The options are: - Use [maplibre-gl](https://maplibre.org/maplibre-gl-js/docs/). See [Get Started](./get-started.md) for how to configure your project. - Stay on `mapbox-gl@1.x`. react-map-gl plans to continue supporting this release in the foreseeable future, however, this version will not include any of the latest features of the map renderer, nor get any future updates from Mapbox. To use your own map service, you will need a custom map style that points to your own [tile source](https://maplibre.org/maplibre-style-spec/sources/), and pass it to `Map` using the `mapStyle` prop. Some alternative map data providers include: - [MapTiler](https://www.maptiler.com) - [Amazon Location Service](https://docs.aws.amazon.com/location/latest/developerguide/map-concepts.html) Useful resources for creating your own map tiles and service: - [Martin Tile Server](https://maplibre.org/martin/introduction.html) - [OpenMapTiles](https://openmaptiles.org) - [Mapbox Vector Tile Spec](https://github.com/mapbox/vector-tile-spec) - [PMTiles](https://github.com/protomaps/PMTiles) - [List of open source tools](https://github.com/mapbox/awesome-vector-tiles) If you are using a third party service that requires header based authentication, you can do this by defining a function to pass to `Map` using the `transformRequest` prop. An example function: ```ts const transformRequest = (url, resourceType) => { if (resourceType === 'Tile' && url.match('yourTileSource.com')) { return { url: url, headers: { 'Authorization': 'Bearer ' + yourAuthToken } } } } ``` ================================================ FILE: docs/get-started/state-management.md ================================================ # State Management There are two ways to use a [Map](../api-reference/maplibre/map.md): - [Uncontrolled](https://reactjs.org/docs/uncontrolled-components.html): The application sets the initial view state (Camera options) when the map is mounted, and the component automatically makes changes to the view states afterwards. This mode works very similarly to the mapbox-gl `Map` class. - [Controlled](https://reactjs.org/docs/forms.html#controlled-components): The application manages the view state, and pass it to the map via props. The map invokes a callback with a new view state during user interaction transition, and the application can decide what to do with it. This mode is the most powerful when an application has other components that need to interact with the map, or implements its own user input and data handling logic. ## Uncontrolled Map You may clone a full app configuration for this example [here](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/basic). ```tsx import * as React from 'react'; import Map from 'react-map-gl/maplibre'; function App() { return ; } ``` ## Controlled Map You may clone a full app configuration for this example [here](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/controlled). ```tsx import * as React from 'react'; import Map from 'react-map-gl/maplibre'; function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 3.5 }); return setViewState(evt.viewState)} mapStyle="mapbox://styles/mapbox/streets-v9" />; } ``` A real-world application likely uses more complicated state flows: - Using map with a state store (Redux) [example](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/redux) - Using map with SSR (Next.js) [example](https://github.com/visgl/react-map-gl/tree/8.0-release/examples/get-started/nextjs) ## Custom Camera Constraints `Map` offers props that set basic constraints for the camera, e.g. `maxBounds`, `minZoom`, `maxPitch`. If you need more complicated logic to constrain the camera, you may use it as a controlled component. The following example restricts the map center inside a GeoJSON geofence: ```tsx import * as React from 'react'; import Map from 'react-map-gl/maplibre'; // npm install @turf/turf import * as turf from '@turf/turf'; // A circle of 5 mile radius of the Empire State Building const GEOFENCE = turf.circle([-74.0122106, 40.7467898], 5, {units: 'miles'}); function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 3.5 }); const onMove = React.useCallback(({viewState}) => { const newCenter = [viewState.longitude, viewState.latitude]; // Only update the view state if the center is inside the geofence if (turf.booleanPointInPolygon(newCenter, GEOFENCE)) { setViewState(viewState); } }, []) return ; } ``` ================================================ FILE: docs/get-started/tips-and-tricks.md ================================================ # Tips and Tricks ## Securing Mapbox Token Because Mapbox tokens are required for the client application to make requests to Mapbox servers, you have to distribute it with your app. It is not possible to stop a visitor to your site from scraping the token. The practice outlined below can help you protect your token from being abused. - Never commit your token in clear text into GitHub or other source control. - In your local dev environment, define the token in an environment variable e.g. `MapboxAccessTokenDev=...` in the command line, or use something like [dotenv](https://github.com/motdotla/dotenv) and put `MapboxAccessTokenDev=...` in a `.env` file. Add `.env` to `.gitignore` so it's never tracked. If your app is deployed by a continuous integration pipeline, follow its documentation and set a secret environment variable. - Create separate tokens for development (often times on `http://localhost`), public code snippet (Gist, Codepen etc.) and production (deployed to `https://mycompany.com`). The public token should be rotated regularly. The production token should have strict [scope and URL restrictions](https://docs.mapbox.com/help/troubleshooting/how-to-use-mapbox-securely/#access-tokens) that only allows it to be used on a domain that you own. - Add the following to your bundler config: import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; ```js /// webpack.config.js const {DefinePlugin} = require('webpack'); module.exports = { ... plugins: [ new DefinePlugin({ 'process.env.MapboxAccessToken': JSON.stringify(process.env.NODE_ENV == 'production' ? process.env.MapboxAccessTokenProd : process.env.MapboxAccessTokenDev) }) ] }; ``` ```js /// rollup.config.js const replace = require('@rollup/plugin-replace').default; module.exports = { ... plugins: [ replace({ 'process.env.MapboxAccessToken': JSON.stringify(process.env.NODE_ENV == 'production' ? process.env.MapboxAccessTokenProd : process.env.MapboxAccessTokenDev) }) ] }; ``` react-map-gl automatically picks up `process.env.MapboxAccessToken` or `process.env.REACT_APP_MAPBOX_ACCESS_TOKEN` if they are defined. Alternatively, you can use your own variable name (e.g. `__SUPER_SECRET_TOKEN__`) and pass it in manually with `mapboxAccessToken={__SUPER_SECRET_TOKEN__}`. ## Minimize Cost from Frequent Re-mounting In a moderately complex single-page app, as the user navigates through the UI, a map component may unmount and mount again many times during a session. Consider the following layout: ```tsx /// Example using Tabs from Material UI {items.map(renderMarker)} {items.map(renderRow)}
``` Every time the user clicks the "table" tab, the map is unmounted. When they click the "map" tab, the map is mounted again. As of v2.0, mapbox-gl generates a [billable event](https://www.mapbox.com/pricing#maploads) every time a Map object is initialized. It is obviously not ideal to get billed for just collapsing and expanding part of the UI. In this case, it is recommended that you set the [reuseMaps](../api-reference/mapbox/map.md#reuseMaps) prop to `true`: ```tsx {items.map(renderMarker)} ``` This bypasses the initialization when a map is removed then added back. ## Performance with Many Markers If your application uses externally managed camera state, like with Redux, the number of React rerenders may be very high when the user is interacting with the map. Consider the following setup: ```tsx import {useSelector, useDispatch} from 'react-redux'; import Map, {Marker} from 'react-map-gl/maplibre'; function MapView() { const viewState = useSelector((s: RootState) => s.viewState); const vehicles = useSelector((s: RootState) => s.vehicles); const dispatch = useDispatch(); const onMove = useCallback(evt => { dispatch({type: 'setViewState', payload: evt.viewState}); }, []); return ( > {vehicles.map(vehicle => ( // vehicle icon ) )} ); } ``` This component is rerendered on every animation frame when the user is dragging the map. If it's trying to render hundreds of markers, the performance lag will become quite visible. One way to improve the performance is `useMemo`: ```tsx const markers = useMemo(() => vehicles.map(vehicle => ( // vehicle icon ) ), [vehicles]); return ( > {markers} ); } ``` This prevents React from rerendering the markers unless they have changed. If your application can do without complicated DOM objects and CSS styling, consider switching to a [symbol layer](https://docs.mapbox.com/mapbox-gl-js/style-spec/layers/#symbol). Layers are rendered in WebGL and are much more performant than markers: ```tsx const vehiclesGeoJSON = useMemo(() => { return { type: 'FeatureCollection', features: vehicles.map(vehicle => turf.point(vehicle.coordinates, vehicle)) }; }, [vehicles]); return ( > ); ``` ## Finding out if a point is within the current viewport There are some situations where you want to know if a point is currently visible on the map. Checking this is simple and can be done like so: ```tsx const mapRef = useRef(); const checkIfPositionInViewport = (lat, lng) => { const bounds = mapRef.current.getBounds(); return bounds.contains([lng, lat]); } return ``` ================================================ FILE: docs/table-of-contents.json ================================================ [ { "type": "category", "label": "Overview", "items": [ "README", "whats-new", "upgrade-guide", "contributing" ] }, { "type": "category", "label": "Developer Guide", "items": [ "get-started/get-started", "get-started/mapbox-tokens", "get-started/state-management", "get-started/adding-custom-data", "get-started/tips-and-tricks" ] }, { "type": "category", "label": "API Reference", "items": [ { "type": "category", "label": "Mapbox", "items": [ "api-reference/mapbox/map", "api-reference/mapbox/attribution-control", "api-reference/mapbox/fullscreen-control", "api-reference/mapbox/geolocate-control", "api-reference/mapbox/layer", "api-reference/mapbox/map-provider", "api-reference/mapbox/marker", "api-reference/mapbox/navigation-control", "api-reference/mapbox/popup", "api-reference/mapbox/scale-control", "api-reference/mapbox/source", "api-reference/mapbox/use-control", "api-reference/mapbox/use-map", "api-reference/mapbox/types" ] }, { "type": "category", "label": "Maplibre", "items": [ "api-reference/maplibre/map", "api-reference/maplibre/attribution-control", "api-reference/maplibre/fullscreen-control", "api-reference/maplibre/geolocate-control", "api-reference/maplibre/layer", "api-reference/maplibre/logo-control", "api-reference/maplibre/map-provider", "api-reference/maplibre/marker", "api-reference/maplibre/navigation-control", "api-reference/maplibre/popup", "api-reference/maplibre/scale-control", "api-reference/maplibre/source", "api-reference/maplibre/terrain-control", "api-reference/maplibre/use-control", "api-reference/maplibre/use-map", "api-reference/maplibre/types" ] } ] } ] ================================================ FILE: docs/upgrade-guide.md ================================================ # Upgrade Guide ## Upgrading to v8.0 - All imports from `react-map-gl` should be replaced with one of the following endpoints: + If using with `mapbox-gl@>=3.5.0`: import from `react-map-gl/mapbox` + If using with `mapbox-gl@<3.5.0`: import from `react-map-gl/mapbox-legacy` - `maplibre-gl@<=3` is no longer supported. - Some TypeScript types have been renamed to align with the official types from the base map libraries: | Old name | New name | |----------|----------| | `MapStyle` | `StyleSpecification` | | `Fog` | `FogSpecification` | | `Light` | `LightSpecification` | | `Terrain` | `TerrainSpecification` | | `Projection` | `ProjectionSpecification` | | `*Layer` | `*LayerSpecification` | | `*SourceRaw` | `*SourceSpecification` | ### MapLibre #### Removed default for `RTLTextPlugin` The default `RTLTextPlugin` loaded from mapbox.com has been removed to align with the default behavior of MapLibre. To keep the previous behavior, specify the `pluginUrl` which was previously used or supply the plugin from any other source: ```tsx ``` ## Upgrading to v7.1 - `maplibre-gl` users no longer need to install `mapbox-gl` or a placeholder package as dependency. Change your imports to the new endpoint `react-map-gl/maplibre`. Components imported from here do not require setting the `mapLib` prop, and use the types defined by `maplibre-gl`. ```tsx title="map-v7.0.tsx" import Map from 'react-map-gl'; import maplibregl from 'maplibre-gl'; function App() { return ; } ``` ```tsx title="map-v7.1.tsx" import Map from 'react-map-gl/maplibre'; // <- mind the updated import function App() { return } ``` If you installed `mapbox-gl` from a placeholder such as `npm:empty-npm-package@^1.0.0` as suggested by the previous version's documentation, it should be removed from your package.json. - The `@types/mapbox-gl` dependency has relaxed its version constraint. If you use `mapbox-gl` as the base map library, it's recommended to explicitly list `@types/mapbox-gl` in your package.json with a version matching that of `mapbox-gl` (v1 or v2). This package is no longer required by the non-mapbox code path, and may be further demoted to an optional peer dependency in a future release. - If you use the `Map` component as a child of the `DeckGL` component from `deck.gl`, upgrade `deck.gl` to `>=8.9.18`. ## Upgrading to v7.0 v7 is a complete rewrite of the library. It is redesigned to be fast, lightweight, fully typed, to behave the same and expose the same APIs as the wrapped map library, and to provide the maximum compatibility with third-party plugins. To take advantages of these new features, you need to make some changes to your code that was previously depending on react-map-gl v5 and v6. > If you are using react-map-gl controls (`Marker`, `Popup`, `NavigationControl` etc.) with deck.gl's `ContextProvider`, do not upgrade to this version. The old approach no longer works with v7. We are moving the support for this use case to a new project that does not depend on mapbox. ### Dependencies - Add `mapbox-gl` (or a compatible fork) to your package.json. `react-map-gl` no longer lists a specific map renderer in its dependencies, so you are free to use it with Mapbox v1, v2 or Maplibre. - `viewport-mercator-project` (an alias of `@math.gl/web-mercator`) is no longer a dependency. You can still install the library on the side as a utility for viewport-related math, but it's no longer required. ### Module exports - `InteractiveMap` and `StaticMap` are removed. Instead, import `Map`. - `setRTLTextPlugin` is removed. Use the `Map` component's `RTLTextPlugin` prop (default enabled). - `MapController` is removed. v7.0 has removed its own implementation of user input handling in favor of the [native handlers](https://docs.mapbox.com/mapbox-gl-js/api/handlers/). If you are using a custom implementation of `MapController`, check if the native handlers offer options to address your application's needs. - `MapContext` and `useMapControl` are removed. Check out the new API [useMap](./api-reference/mapbox/use-map.md) and [useControl](./api-reference/mapbox/use-control.md). - The overlay components (`HTMLOverlay`, `CanvasOverlay` and `SVGOverlay`) are removed. Check out [this example](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/custom-overlay) for implementing similar controls in your own application. - `LinearInterpolator` and `FlyToInterpolator` are removed. Use `map.easeTo()` and `map.flyTo()` instead, see [this example](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/viewport-animation). ### Map [documentation](./api-reference/mapbox/map.md) - Renamed props for better consistency with the wrapped library: + `mapboxApiAccessToken` is now `mapboxAccessToken` + `mapboxApiUrl` is now `baseApiUrl` + `preventStyleDiffing` (default `false`) is replaced with `styleDiffing` (default `true`) - `mapStyle` should be explicitly specified. The default value has changed from `"mapbox://styles/mapbox/light-v9"` to an empty style. - The following props are removed and apps should use `style` instead: + `width` + `height` + `visible` - `onViewportChange`, `onViewStateChange` and `onInteractionStateChange` are removed. You can either use `Map` as an uncontrolled component with the new `initialViewState` prop, or if you need to manage the camera state externally (e.g. in Redux), use the `onMove` callback instead. See examples in [state management](./get-started/state-management.md). - `transition*` props are removed. Use `map.easeTo()` and `map.flyTo()` instead, see [this example](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/viewport-animation). - `mapOptions` is removed. Almost all of the options for the native `Map` class are exposed as props. - `onHover` is removed. Use `onMouseMove` or `onMouseEnter`. - The event argument is changed for all interaction callbacks. See documentation for details. - `getCursor` is removed as part of the effort to get `Map` behave the same as the native component. To set the cursor, use the `cursor` prop. Follow [this example](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/custom-cursor) to change cursor on hover. - `touchAction` and `eventRecognizerOptions` are removed. Check out the `cooperativeGestures` prop. ### Other components - `capture*` props are removed. - `*label` props are removed. Use `Map`'s `locale` prop. - All map controls' props are now strictly aligned with their mapbox-gl counterparts. In heading this direction, we are able to remove a significant amount of custom code and have the components behave more predictably for developers switching from the native library. If your application is relying on an old feature that is no longer supported, please open a topic on [Discussion](https://github.com/visgl/react-map-gl/discussions) so we can review on a case-by-case basis. ## Upgrading to v5.3/v6.1 - `MapContext` is now an official API. The experimental `_MapContext` export will be removed in a future release. - `react-virtualized-auto-sizer` is no longer a dependency. - Inertia has been enabled by default on the map controller. To revert to the behavior in previous versions, set the [interaction options](https://github.com/visgl/react-map-gl/tree/6.1-release/docs/api-reference/interactive-map.md#interaction-options): ```js const CONTROLLER_OPTS = { dragPan: {inertia: 0}, dragRotate: {inertia: 0}, touchZoom: {inertia: 0} }; ``` - `Source` and `Layer` components no longer expose imperative methods via `ref` as part of the migration to functional components. This is to comply with the pattern recommended by the latest React. + If you used to call `sourceRef.getSource()`, it can be replaced with `mapRef().getMap().getSource(sourceId)`. + If you used to call `layerRef.getLayer()`, it can be replaced with `mapRef().getMap().getLayer(layerId)`. ## Upgrading to v6 - A valid Mapbox access token is always required. - The default value of `InteractiveMap`'s `maxPitch` prop is changed to `85` from `60`. - `mapbox-gl` v2 introduced a breaking change to the build system. Transpiling it may result in a crash in the production build with the message `m is not defined`. Find solutions in [this thread](https://github.com/mapbox/mapbox-gl-js/issues/10173). ## Upgrading to v4 - `onChangeViewport` is removed, use `onViewportChange` instead - `Immutable.js` is no longer a dependency - Export `experimental.MapControls` is removed, use `MapController` instead - `InteractiveMap`'s `mapControls` prop is renamed to `controller` - Removed support for the deprecated `interactive` property on the layer styles. Use the `interactiveLayerIds` prop to specify which layers are clickable. ## Upgrading to v3.2 - The latest mapbox-gl release requires stylesheet to be included at all times. See [Get Started](./get-started/get-started.md) for information about styling. - Immutable.js is no longer a hard dependency and will be removed in the next major release. If you are importing immutable in your application, it is recommended that you explicitly list it in the application's dependencies. ## Upgrading to v3 v3 is a major upgrade of react-map-gl. While we have tried to gently deprecated any changed or removed features, a few breaking changes could not be avoided. ### Version Requirements - The **Node Version Requirement** for **building** react-map-gl is now **>=v6.4.0**. Using prebuilt react-map-gl does **NOT** has this limitation. This is introduced by [Mapbox GL JS v0.38.0](https://github.com/mapbox/mapbox-gl-js/releases/tag/v0.38.0) ### MapGL Component * **Two Map Components** - v3 now splits the Map component into two React components: `StaticMap` and `InteractiveMap`. `InteractiveMap` is the default export, and designed to be as compatible as possible with the v2 default component. #### `onChangeViewport` callback now includes `width` and `height`. The `viewport` parameter passed to the `onChangeViewport` callback now includes `width` and `height`. Application code that composed the `viewport` with `width` and `height` may have to be updated. Please double check your render code if you relied on this behavior. ```js // BAD: 'width' and 'height' below will be overridden by what's in the 'viewport' object // GOOD: 'width' and 'height' below will override the values in 'viewport' ``` ### Overlays * **Some Overlays Moved to Examples** - Some less frequently used overlays (`DraggablePointsOverlay`, `ChoroplethOverlay`, `ScatterplotOverlay`), have been moved to examples. Most users are now using mapbox styles or deck.gl layers and removing these overlays reduces the size of the react-map-gl library for the majority of users that don't need them. If you still use them, simply copy the overlay source file(s) into your application. * **Overlays must be Children of the Map** - Overlays **must** now be rendered as children of the main `react-map-gl` component to automatically sync with the map viewport. ### `fitBounds` utility function The `fitBounds` utility has been moved to the [math.gl](https://github.com/uber-web/math.gl) library. The function can now be called as follows: ```js import WebMercatorViewport from 'viewport-mercator-project'; const viewport = new WebMercatorViewport({width: 600, height: 400}); const bound = viewport.fitBounds( [[-73.9876, 40.7661], [-72.9876, 41.7661]], {padding: 20, offset: [0, -40]} ); // => bounds: instance of WebMercatorViewport // {longitude: -73.48760000000007, latitude: 41.268014439447484, zoom: 7.209231188444142} ``` ### Deprecations We have started to deprecate a few React props. In all the cases below, the old `props` will still work (you'll get a warning in the console), but they will likely be removed in the next major version of react-map-gl so you should start using the new `props` as soon as possible. | Old Prop | New Prop | | --- | --- | | `onChangeViewport()` | `onViewportChange()` | | `onHoverFeatures()` | `onHover()` | | `onClickFeatures()` | `onClick()` | | `perspectiveEnabled [default: false]` | `dragRotate [default: true]` | ## Upgrading to v2 v2 is API compatible with v1, however if you are still using `v1` of react-map-gl, make sure that you first upgrade: * Your `node` version to `v4` or higher * Your `react` version to `15.4` or higher. Background: `mapbox-gl` 0.31.0 introduced a hard dependency on Node >= v4. ## Upgrading to v1 (Upgrading from 0.6.x) * **Importing Overlays** - The map overlay components (`HTMLOverlay`, `CanvasOverlay`, `SVGOverlay` etc) are now named exports. They previously had to be imported via their relative source paths: ```js // v1.0 import MapGL, {SVGOverlay} from 'react-map-gl'; // v0.6 import MapGL from 'react-map-gl'; import SVGOverlay from 'react-map-gl/src/api-reference/svg-overlay';. ``` * **Map State** - The map state reported by `onViewportChanged` will now contain additional state fields (tracking not only `pitch` and `bearing` needed for perspective mode, but also transient information about how the projection is being changed by the user). * This information must be passed back to the react-map-gl component in the next render. * To simplify and future proof applications, it is recommended to simply save the entire `mapState` in your app store whenever it changes and then pass it back to the component rather than trying to keep track of individual fields (like `longitude`, `latitude` and `zoom`). ================================================ FILE: docs/whats-new.md ================================================ # What's new ## react-map-gl v8.1 Release date: Oct 2025 The core logic in the Mapbox GL JS wrapper has been rewritten to use [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) to intercept camera updates. We expect the new approach to improve camera synchronization between the native controller and React props when terrain and/or non-mercator projections are used. See more backgrounds in [#2514](https://github.com/visgl/react-map-gl/pull/2514). The Maplibre wrapper is unaffected by this change. ## react-map-gl v8.0 Release date: Jan 2025 - First version to support Mapbox GL JS' official types and MapLibre GL JS v5. This version fully separates the code that support each compatible map library: + `react-map-gl/mapbox`: for use with `mapbox-gl>=3.5.0` + `react-map-gl/maplibre`: for use with `maplibre-gl>=4` + `react-map-gl/mapbox-legacy`: for use with `mapbox-gl` v1.x and v2.x and `@types/mapbox-gl` - As a result, each endpoint now have slightly smaller bundle size and more precise types. - Maplibre wrapper is expected to have better functionality and performance than v7 by utilizing an [upstream API](https://github.com/maplibre/maplibre-gl-js/issues/1545) for the React use case. For a full list of breaking changes, please visit the [upgrade guide](./upgrade-guide.md#upgrading-to-v80). ## react-map-gl v7.1 Release date: June 2023 - To better accommodate the API divergence between Mapbox and Maplibre, this version adds a new endpoint `react-map-gl/maplibre`. The new endpoint exports identical components as `react-map-gl`, but typed for `maplibre-gl` instead. After switching to this new endpoint, `maplibre-gl` users no longer need to install `mapbox-gl` or a placeholder package as dependency. See [upgrade guide](./upgrade-guide.md) for an example. - `Marker`, `Popup` and `GeolocateControl` components now expose the native instance via React ref. ## react-map-gl v7.0 Release date: Feb 4, 2022 v7 is a complete rewrite of the library. It addresses many long-standing issues in v5 and v6 limited by legacy architecture decisions. The most notable results of this redesign are: - Performance: minimize the overhead of React, offer the same fast and smooth interaction as the native library - Lightweight: the ESM build size is reduced from 219k to 57k - Predictability: Components behave the same as their mapbox counterparts. Props are mapped 1:1 from the native options wherever appropriate. Almost all imperative APIs (`flyTo`, `fitBounds` etc.) can now be called directly without breaking the React binding. - Compatibility: first and third-party plugins! Directly use [mapbox-gl-draw](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/draw-polygon), [mapbox-gl-geocoder](https://github.com/visgl/react-map-gl/tree/7.0-release/examples/geocoder), to name a few. - TypeScript compliant: the code base is now entirely written in TypeScript, and all types can be [imported](./api-reference/mapbox/types.md). Visit the [upgrade guide](./upgrade-guide.md) if you are trying to upgrade from v5 and v6. ## react-map-gl v5.3/v6.1 Release date: Jan 27, 2020 ### Highlights - **TypeScript and Flow typings** are now published with the library - **More controller customizations.** Smooth easing on wheel scroll, three-finger gesture to change pitch, inertia after pan/pinch, and customizable keyboard navigation speed. See the updated [interaction options](https://github.com/visgl/react-map-gl/tree/6.1-release/docs/api-reference/interactive-map.md#interaction-options) for details. - A new [eventRecognizerOptions](https://github.com/visgl/react-map-gl/tree/6.1-release/docs/api-reference/interactive-map.md#eventrecognizeroptions) prop is added for fine-tuning the interaction experience. - New component: [AttributionControl](https://github.com/visgl/react-map-gl/tree/6.1-release/docs/api-reference/attribution-control.md) - Promoted to official API: [MapContext](https://github.com/visgl/react-map-gl/tree/6.1-release/docs/api-reference/map-context.md) - Resolved React error over attempted state update during render - `GeolocateControl` added supports for `showAccuracyCircle` - All controls now support inline styling with a `style` prop - All components and examples have been rewritten as functional components ## react-map-gl v6.0 Release date: Dec 16, 2020 ### What's Changed The 6.0 release upgrades its Mapbox GL JS dependency to v2.0. There are [important changes](https://github.com/mapbox/mapbox-gl-js/releases/tag/v2.0.0) to mapbox-gl's license and pricing model in this milestone. If you are NOT using a Mapbox account (e.g. self-hosting map tiles), do **NOT** upgrade to this version, and consider your options discussed in [this document](./get-started/mapbox-tokens.md). See [upgrade guide](./upgrade-guide.md) for a complete list of breaking changes. ## react-map-gl v5.2 Release date: Jan 6, 2020 ### Highlights - **New Components**: [`ScaleControl`](https://github.com/visgl/react-map-gl/tree/5.2-release/docs/api-reference/scale-control.md) - **NavigationControl**: new `label` prop - **GeolocateControl**: new `label`, `onGeolocate`, `auto` props - **New Export**: `WebMercatorViewport` is re-exported from the `viewport-mercator-project` library for ease of use. It's recommended to import it from `react-map-gl` instead to avoid future dependency change. - **New Example**: [Clusters](https://visgl.github.io/react-map-gl/examples/clusters) ## react-map-gl v5.1 Release date: Oct 30, 2019 ### Highlights - **New Components**: [`Layer`](https://github.com/visgl/react-map-gl/tree/5.1-release/docs/components/layer.md) and [`Source`](https://github.com/visgl/react-map-gl/tree/5.1-release/docs/components/source.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **Viewport transition**: `transitionDuration` can be set to `'auto'` when using [`FlyToInterpolator`](https://github.com/visgl/react-map-gl/tree/5.1-release/docs/components/fly-to-interpolator.md). - **New Example**: Add an [example](https://visgl.github.io/react-map-gl/examples/draw-polygon) with drawing library [react-map-gl-draw](https://github.com/uber/nebula.gl/tree/master/modules/react-map-gl-draw). ## react-map-gl v5.0 Release date: May 31, 2019 ### What's Changed The only change between the 5.0 release and the latest 4.1 release is Mapbox GL JS v1.0. By using this version, you opt into Mapbox's new pricing model, which bills per map load instead of map views. 5.0.x and 4.1.x will continue to update in parallel with otherwise identical features until November 2019 when Mapbox moves all users of 0.xx to a new pricing scheme. For more details, see mapbox's [changelog](https://github.com/mapbox/mapbox-gl-js/releases/tag/v1.0.0) and [blog post](https://blog.mapbox.com/new-pricing-46b7c26166e7). Alongside Mapbox GL JS's new milestone, we have relaxed the `mapbox-gl` dependency from locking minor release (`~0.53.0`) to major release (`^1.0.0`). This will allow developers to upgrade faster without waiting for a new release from react-map-gl. ## react-map-gl v4.1 Release date: Mar 14, 2019 ### Highlights - **New Components**: [`FullscreenControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/fullscreen-control.md), [`GeolocateControl`](https://github.com/visgl/react-map-gl/tree/4.1-release/docs/components/geolocate-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **New callback props** `InteractiveMap` supports more callbacks: + `onNativeClick` ## react-map-gl v4.0 Release date: Nov 5, 2018 ### Highlights - **Relative dimensions** Both `InteractiveMap` and `StaticMap` now support CSS strings supplied to map `width` and `height` props. New `onResize` callback is fired when the map resizes. - **React 16** Upgrade to React 16.3 context and ref patterns - **Babel 7** Upgrade build system to Babel 7, better support for tree-shaking - **Style diffing** Now use Mapbox's native style diffing. Immutable is no longer required. - **Draggable Markers** `Marker` component now supports a new prop `draggable`, along with callbacks `onDragStart`, `onDrag`, and `onDragEnd`. - **3d Popups** `Popup` component now supports a new prop `sortByDepth` to enable proper occlusion when multiple popups are used in a tilted map. - **Interaction states** `onViewportChange` is now called with richer descriptors of the user interaction, including `isPanning`, `isZooming` and `isRotating`. - **Interactive layers** Dropped the requirement for the deprecated `interactive` property on the layer styles. Use the `interactiveLayerIds` prop to specify which layers are clickable. - **New callback props** `InteractiveMap` supports more callbacks: + `onDblClick` + `onMouseDown` + `onMouseMove` + `onMouseUp` + `onTouchStart` + `onTouchMove` + `onTouchEnd` + `onMouseEnter` + `onMouseLeave` + `onWheel` + `onMouseOut` See [upgrade guide](./upgrade-guide.md) for breaking changes. ## react-map-gl v3.3 Release date: July, 2018 ### Highlights - **New `viewState` Property**: Makes it possible to specify all map state properties (`longitude`, `latitude`, `zoom`, `bearing` and `pitch`) as a single property. - **New `onViewStateChange` callback**: An alternative callback that matches the new `viewState` prop. ## react-map-gl v3.2 Realease date: January, 2018 ### Highlights - **Viewport transition**: feature equivalent to Mapbox's flyTo and easeTo; smooth transition when using keyboard navigation or the NavigationControl. - **Better parity of Mapbox interaction**: navigation using keyboard and the navigation control matches Mapbox behavior, including smooth transition when zooming and panning. - **Support for Map Reuse (experimental)**: A new property `reuseMaps` is provided for applications that create and destroy maps, to help work around a mapbox-gl resource leak issue that can lead to a browser crash in certain situations. - **mapbox-gl 0.42.2** - **New props** of the InteractiveMap component: + Map creation: `transformRequest`, `reuseMaps` + Interaction: `touchZoom`, `touchRotate` + Transition: `transitionDuration`, `transitionInterpolator`, `transitionEasing`, `transitionInterruption`, `onTransitionStart`, `onTransitionInterrupt`, `onTransitionEnd` ## react-map-gl v3.1 Release date: October 19, 2017 ### Highlights - **Event handling** + Support right mouse drag to rotate + Support keyboard navigation + Allow controls and overlays to block map interactions - **React 16** - react-map-gl is now being tested with React 16, but the React peer dependency requirement is unchanged at `>=15.4.x`. - **mapbox-gl v0.40.1** - **No Token warning**: react-map-gl now renders an HTML message if no mapbox token is supplied. ## react-map-gl v3.0 Release date: July 27th, 2017 ### Highlights - **Latest Mapbox GL JS**: Bumps `Mapbox GL JS` to [0.38](https://github.com/mapbox/mapbox-gl-js/releases). - **Multi-Touch Support**: Full support for multi-touch gestures such as pinch-to-zoom and rotate. - **New Components**: The `MapGL` component has been split into [`StaticMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/static-map.md) and [`InteractiveMap`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/interactive-map.md) (the default). Also, [`Popup`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/popup.md), [`Marker`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/marker.md), [`NavigationControl`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/navigation-control.md) have been added to provide better React parity with the `Mapbox GL JS` API. - **Improved Overlay Components**: Supplying viewport props (`width` `height` `zoom` `longitude` and `latitude`) are no longer required if you render [`SVGOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/svg-overlay.md), [`CanvasOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/canvas-overlay.md) or [`HTMLOverlay`](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/overlays/html-overlay.md) as a child of the map. Perspective mode is now supported in all overlays. - **New Props**: `maxPitch`, `minPitch`, `dragPan`, `doubleClickZoom`, `touchZoomRotate`, `scrollZoom` are now provided to allow granular control of map interactivity. - **Documentation**: Significantly expanded and linked with our other geospatial frameworks. - **Examples**: New stand-alone examples to get you started instantly with the new features. - **Event Handling**: New event handling architecture that enables full customization of event handling (experimental). ### Components #### [InteractiveMap (New, MapGL replacement)](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/interactive-map.md) This is a wrapper on top of `StaticMap`. It takes all the props of `StaticMap` and additional ones such as `onViewportChange`, `scrollZoom`, `dragRotate`, etc. to control interactivity on the map. See [Source Code](https://github.com/visgl/react-map-gl/tree/7.0-release/src/components/interactive-map.js) for more information. #### [StaticMap (New)](https://github.com/visgl/react-map-gl/tree/3.0-release/docs/components/static-map.md) This is the React wrapper around `Mapbox GL JS` and takes in viewport properties such as `width`, `height`, `latitude`, `longitude`. Style diffing and updating logic also live here. See [Source Code](https://github.com/visgl/react-map-gl/tree/7.0-release/src/components/static-map.js) for more information. #### Overlays * Three overlays (`ScatterplotOverlay`, `DraggablePointsOverlay`, `ChoroplethOverlay`), have been moved out of the library and are now only provided as examples. ### Property Changes - **Property Names** - some prop names have been modernized, the old ones will still work for now with a warning. - **Internal Properties** such as `isHovering`, `isDragging`, `startDragLngLat` have been removed. These were never meant to be useful publicly and have caused confusions in the past. ### Utilities * **fitBounds**: `fitBounds` has been moved to another repository and has been rewritten to provide a more logical interface. For more information, see the `Upgrade Guide`. ## react-map-gl v2.0 Date: Jan 17, 2017 ### Highlights - **Latest mapbox-gl**: Bump `mapbox-gl` to v0.31.0 - **new maxZoom prop** - Add `maxZoom` prop and defaults to `20` - **New onLoad prop** - Add `onLoad` event handler - **new onClick prop** - Add `onClick` prop handler (#140) ## react-map-gl v1.0 * **Perspective Mode** - Now supports `bearing` and `pitch` properties, per mapbox-gl api documentation. These props default to 0 which means that maps will still be rendered in flat/ortographic mode when they are not provided * **Support for ES6 imports** - The map overlay components (HTMLOverlay, CanvasOverlay, SVGOverlay etc) previously had to be imported via their relative source paths can now be imported directly. ## react-map-gl v0.6 Initial public version ================================================ FILE: examples/.data/bart-station.json ================================================ [ {"name":"Lafayette (LAFY)","coordinates":[-122.123801,37.893394]}, {"name":"12th St. Oakland City Center (12TH)","coordinates":[-122.271604,37.803664]}, {"name":"16th St. Mission (16TH)","coordinates":[-122.419694,37.765062]}, {"name":"19th St. Oakland (19TH)","coordinates":[-122.269029,37.80787]}, {"name":"24th St. Mission (24TH)","coordinates":[-122.418466,37.752254]}, {"name":"Ashby (ASHB)","coordinates":[-122.26978,37.853024]}, {"name":"Balboa Park (BALB)","coordinates":[-122.447414,37.721981]}, {"name":"Bay Fair (BAYF)","coordinates":[-122.126871,37.697185]}, {"name":"Castro Valley (CAST)","coordinates":[-122.075567,37.690754]}, {"name":"Civic Center/UN Plaza (CIVC)","coordinates":[-122.413756,37.779528]}, {"name":"Colma (COLM)","coordinates":[-122.466233,37.684638]}, {"name":"Coliseum/Oakland Airport (COLS)","coordinates":[-122.197273,37.754006]}, {"name":"Concord (CONC)","coordinates":[-122.029095,37.973737]}, {"name":"Daly City (DALY)","coordinates":[-122.469081,37.706121]}, {"name":"Downtown Berkeley (DBRK)","coordinates":[-122.268045,37.869867]}, {"name":"El Cerrito del Norte (DELN)","coordinates":[-122.317269,37.925655]}, {"name":"Dublin/Pleasanton (DUBL)","coordinates":[-121.900367,37.701695]}, {"name":"Embarcadero (EMBR)","coordinates":[-122.396742,37.792976]}, {"name":"Fremont (FRMT)","coordinates":[-121.9764,37.557355]}, {"name":"Fruitvale (FTVL)","coordinates":[-122.224274,37.774963]}, {"name":"Glen Park (GLEN)","coordinates":[-122.434092,37.732921]}, {"name":"Hayward (HAYW)","coordinates":[-122.087967,37.670399]}, {"name":"Lake Merritt (LAKE)","coordinates":[-122.265609,37.797484]}, {"name":"MacArthur (MCAR)","coordinates":[-122.267227,37.828415]}, {"name":"Millbrae (MLBR)","coordinates":[-122.38666,37.599787]}, {"name":"Montgomery St. (MONT)","coordinates":[-122.401407,37.789256]}, {"name":"North Berkeley (NBRK)","coordinates":[-122.283451,37.87404]}, {"name":"North Concord/Martinez (NCON)","coordinates":[-122.024597,38.003275]}, {"name":"Orinda (ORIN)","coordinates":[-122.183791,37.878361]}, {"name":"Pleasant Hill/Contra Costa Centre (PHIL)","coordinates":[-122.056013,37.928403]}, {"name":"Pittsburg/Bay Point (PITT)","coordinates":[-121.945154,38.018914]}, {"name":"El Cerrito Plaza (PLZA)","coordinates":[-122.299272,37.903059]}, {"name":"Powell St. (POWL)","coordinates":[-122.406857,37.784991]}, {"name":"Richmond (RICH)","coordinates":[-122.353165,37.936887]}, {"name":"Rockridge (ROCK)","coordinates":[-122.251793,37.844601]}, {"name":"San Leandro (SANL)","coordinates":[-122.161311,37.722619]}, {"name":"San Bruno (SBRN)","coordinates":[-122.416038,37.637753]}, {"name":"San Francisco Int'l Airport (SFIA)","coordinates":[-122.392612,37.616035]}, {"name":"South Hayward (SHAY)","coordinates":[-122.057551,37.6348]}, {"name":"South San Francisco (SSAN)","coordinates":[-122.444116,37.664174]}, {"name":"Union City (UCTY)","coordinates":[-122.017867,37.591208]}, {"name":"Walnut Creek (WCRK)","coordinates":[-122.067423,37.905628]}, {"name":"West Dublin/Pleasanton (WDUB)","coordinates":[-121.928099,37.699759]}, {"name":"West Oakland (WOAK)","coordinates":[-122.294582,37.804675]} ] ================================================ FILE: examples/.data/cities.json ================================================ [ {"city":"New York","population":"8,175,133","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Above_Gotham.jpg/240px-Above_Gotham.jpg","state":"New York","latitude":40.6643,"longitude":-73.9385}, {"city":"Los Angeles","population":"3,792,621","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/5/57/LA_Skyline_Mountains2.jpg/240px-LA_Skyline_Mountains2.jpg","state":"California","latitude":34.0194,"longitude":-118.4108}, {"city":"Chicago","population":"2,695,598","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/8/85/2008-06-10_3000x1000_chicago_skyline.jpg/240px-2008-06-10_3000x1000_chicago_skyline.jpg","state":"Illinois","latitude":41.8376,"longitude":-87.6818}, {"city":"Houston","population":"2,100,263","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/6/60/Aerial_views_of_the_Houston%2C_Texas%2C_28005u.jpg/240px-Aerial_views_of_the_Houston%2C_Texas%2C_28005u.jpg","state":"Texas","latitude":29.7805,"longitude":-95.3863}, {"city":"Phoenix","population":"1,445,632","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/b/b9/Downtown_Phoenix_Aerial_Looking_Northeast.jpg/207px-Downtown_Phoenix_Aerial_Looking_Northeast.jpg","state":"Arizona","latitude":33.5722,"longitude":-112.0880}, {"city":"Philadelphia","population":"1,526,006","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Philly_skyline.jpg/240px-Philly_skyline.jpg","state":"Pennsylvania","latitude":40.0094,"longitude":-75.1333}, {"city":"San Antonio","population":"1,327,407","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Downtown_San_Antonio_View.JPG/240px-Downtown_San_Antonio_View.JPG","state":"Texas","latitude":29.4724,"longitude":-98.5251}, {"city":"San Diego","population":"1,307,402","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/5/53/US_Navy_110604-N-NS602-574_Navy_and_Marine_Corps_personnel%2C_along_with_community_leaders_from_the_greater_San_Diego_area_come_together_to_commemora.jpg/240px-US_Navy_110604-N-NS602-574_Navy_and_Marine_Corps_personnel%2C_along_with_community_leaders_from_the_greater_San_Diego_area_come_together_to_commemora.jpg","state":"California","latitude":32.8153,"longitude":-117.1350}, {"city":"Dallas","population":"1,197,816","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/a/ab/Dallas_skyline_daytime.jpg/240px-Dallas_skyline_daytime.jpg","state":"Texas","latitude":32.7757,"longitude":-96.7967}, {"city":"San Jose","population":"945,942","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/1/1e/Downtown_San_Jose_skyline.PNG/240px-Downtown_San_Jose_skyline.PNG","state":"California","latitude":37.2969,"longitude":-121.8193}, {"city":"Austin","population":"790,390","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/9/97/Austin2012-12-01.JPG/240px-Austin2012-12-01.JPG","state":"Texas","latitude":30.3072,"longitude":-97.7560}, {"city":"Jacksonville","population":"821,784","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/f/f3/Skyline_of_Jacksonville_FL%2C_South_view_20160706_1.jpg/240px-Skyline_of_Jacksonville_FL%2C_South_view_20160706_1.jpg","state":"Florida","latitude":30.3370,"longitude":-81.6613}, {"city":"San Francisco","population":"805,235","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/6/6a/San_Francisco_skyline_from_Coit_Tower.jpg/240px-San_Francisco_skyline_from_Coit_Tower.jpg","state":"California","latitude":37.7751,"longitude":-122.4193}, {"city":"Columbus","population":"787,033","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/f/fc/Columbus-ohio-skyline-panorama.jpg/240px-Columbus-ohio-skyline-panorama.jpg","state":"Ohio","latitude":39.9848,"longitude":-82.9850}, {"city":"Indianapolis","population":"820,445","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/1/16/Downtown_indy_from_parking_garage_zoom.JPG/213px-Downtown_indy_from_parking_garage_zoom.JPG","state":"Indiana","latitude":39.7767,"longitude":-86.1459}, {"city":"Fort Worth","population":"741,206","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/d/db/FortWorthTexasSkylineW.jpg/240px-FortWorthTexasSkylineW.jpg","state":"Texas","latitude":32.7795,"longitude":-97.3463}, {"city":"Charlotte","population":"731,424","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Charlotte_skyline45647.jpg/222px-Charlotte_skyline45647.jpg","state":"North Carolina","latitude":35.2087,"longitude":-80.8307}, {"city":"Seattle","population":"608,660","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/3/36/SeattleI5Skyline.jpg/240px-SeattleI5Skyline.jpg","state":"Washington","latitude":47.6205,"longitude":-122.3509}, {"city":"Denver","population":"600,158","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/0/0b/DenverCP.JPG/240px-DenverCP.JPG","state":"Colorado","latitude":39.7618,"longitude":-104.8806}, {"city":"El Paso","population":"649,121","image":"http://upload.wikimedia.org/wikipedia/commons/thumb/6/6d/Downtown_El_Paso_at_sunset.jpeg/240px-Downtown_El_Paso_at_sunset.jpeg","state":"Texas","latitude":31.8484,"longitude":-106.4270} ] ================================================ FILE: examples/.data/feature-example-sf.json ================================================ { "type": "FeatureCollection", "features": [ { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.391701,37.794113], [-122.39198,37.793906], [-122.391614,37.793571], [-122.391714,37.793459], [-122.388816,37.791005], [-122.388932,37.790919], [-122.388616,37.790348], [-122.388076,37.790518], [-122.388375,37.790334], [-122.388225,37.790032], [-122.385852,37.790951], [-122.385496,37.790559], [-122.387589,37.789838], [-122.387289,37.789347], [-122.385303,37.789838], [-122.38512,37.789313], [-122.387174,37.788807], [-122.387032,37.788255], [-122.385261,37.788537], [-122.385136,37.788156], [-122.38739,37.787736], [-122.387415,37.787269], [-122.3845,37.787437], [-122.384342,37.785728], [-122.387577,37.785485], [-122.38765,37.784929], [-122.385546,37.785009], [-122.385455,37.784711], [-122.387477,37.784493], [-122.387691,37.784412], [-122.387722,37.783928], [-122.385271,37.784049], [-122.38525,37.78379], [-122.38572,37.783774], [-122.38573,37.78354], [-122.386088,37.783435], [-122.387732,37.783282], [-122.387773,37.782911], [-122.388426,37.781801], [-122.388189,37.784771], [-122.388504,37.785348], [-122.389694,37.786243], [-122.39141,37.785103], [-122.39146,37.7855], [-122.393512,37.784564], [-122.394567,37.783783], [-122.396711,37.785549], [-122.398941,37.783785], [-122.400955,37.785389], [-122.399523,37.786631], [-122.39999,37.787004], [-122.401497,37.785824], [-122.403374,37.787401], [-122.403427,37.787676], [-122.393875,37.795248], [-122.392429,37.793835], [-122.391701,37.794113] ] ] }, "id": "94105", "properties": { "id": 94105, "neighborhood": "Rincon Hill" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.387773,37.782911], [-122.38474,37.782975], [-122.384693,37.78256], [-122.387778,37.782318], [-122.387757,37.781825], [-122.385561,37.781946], [-122.385521,37.781607], [-122.387737,37.781454], [-122.38743,37.778402], [-122.385306,37.778443], [-122.387471,37.778322], [-122.389642,37.777478], [-122.390383,37.777037], [-122.391116,37.777571], [-122.393279,37.775838], [-122.393858,37.776284], [-122.396169,37.774505], [-122.39557,37.774012], [-122.40004,37.7705], [-122.395085,37.766537], [-122.394825,37.766551], [-122.394286,37.766114], [-122.393456,37.765089], [-122.393013,37.764089], [-122.387845,37.764369], [-122.386873,37.765646], [-122.386312,37.765628], [-122.386523,37.765339], [-122.386427,37.764449], [-122.386725,37.76414], [-122.386629,37.76392], [-122.387081,37.76357], [-122.386533,37.763395], [-122.386581,37.763239], [-122.386331,37.763148], [-122.386187,37.763369], [-122.385513,37.763308], [-122.385484,37.763163], [-122.385186,37.763369], [-122.385099,37.762353], [-122.384723,37.76214], [-122.38429,37.762162], [-122.384473,37.764079], [-122.384319,37.764072], [-122.384098,37.762261], [-122.38326,37.762322], [-122.383289,37.762543], [-122.383771,37.762573], [-122.383809,37.764277], [-122.383289,37.764148], [-122.383116,37.762467], [-122.382337,37.762482], [-122.382519,37.764647], [-122.382336,37.764639], [-122.382125,37.762425], [-122.381894,37.762425], [-122.381865,37.762745], [-122.381682,37.762737], [-122.381643,37.764852], [-122.381153,37.764951], [-122.380883,37.764776], [-122.380874,37.763308], [-122.380691,37.763293], [-122.380383,37.760219], [-122.379507,37.76028], [-122.379776,37.763506], [-122.379526,37.763513], [-122.379218,37.759968], [-122.381288,37.759787], [-122.381327,37.759353], [-122.381202,37.759322], [-122.381317,37.75901], [-122.381182,37.758995], [-122.381288,37.75866], [-122.381134,37.758638], [-122.38125,37.758318], [-122.381096,37.758211], [-122.38124,37.758211], [-122.3815,37.75777], [-122.381481,37.757549], [-122.381288,37.755936], [-122.380787,37.755487], [-122.380797,37.755258], [-122.384109,37.75497], [-122.384109,37.754719], [-122.38333,37.754689], [-122.382868,37.754384], [-122.382896,37.753699], [-122.382723,37.753418], [-122.381703,37.753197], [-122.381433,37.752999], [-122.380095,37.752923], [-122.380089,37.752759], [-122.381482,37.752782], [-122.382078,37.753131], [-122.382933,37.753184], [-122.387833,37.752817], [-122.387666,37.750267], [-122.391705,37.750133], [-122.401546,37.74945], [-122.403798,37.749443], [-122.403022,37.752336], [-122.403364,37.752366], [-122.403524,37.754463], [-122.40315,37.754488], [-122.403328,37.756082], [-122.403585,37.756818], [-122.403428,37.756871], [-122.40405,37.757619], [-122.405604,37.758851], [-122.406015,37.759409], [-122.406167,37.759315], [-122.40645,37.760114], [-122.406451,37.760865], [-122.40604,37.761865], [-122.405859,37.761815], [-122.405832,37.762199], [-122.405271,37.763272], [-122.405115,37.764635], [-122.399688,37.765005], [-122.3998,37.766807], [-122.400422,37.767291], [-122.40001,37.767614], [-122.400915,37.768096], [-122.400881,37.767518], [-122.401851,37.767416], [-122.402021,37.768998], [-122.401768,37.769145], [-122.401685,37.769721], [-122.402091,37.769716], [-122.402105,37.769912], [-122.403477,37.769842], [-122.404003,37.77018], [-122.403723,37.770182], [-122.399425,37.773612], [-122.405629,37.778502], [-122.396711,37.785549], [-122.394567,37.783783], [-122.393512,37.784564], [-122.39146,37.7855], [-122.39141,37.785103], [-122.389694,37.786243], [-122.388504,37.785348], [-122.388189,37.784771], [-122.388426,37.781801], [-122.387773,37.782911] ] ] }, "id": "94107", "properties": { "id": "94107", "neighborhood": "South Beach" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.404959,37.795337], [-122.404055,37.790751], [-122.402694,37.790937], [-122.402535,37.790006], [-122.403858,37.789819], [-122.403478,37.787965], [-122.403247,37.787814], [-122.405883,37.785718], [-122.406236,37.785793], [-122.406602,37.787583], [-122.408244,37.787369], [-122.408655,37.789244], [-122.411913,37.788812], [-122.41229,37.790669], [-122.413931,37.79047], [-122.414883,37.79503], [-122.411553,37.795409], [-122.411484,37.795033], [-122.411024,37.795145], [-122.411087,37.795467], [-122.407091,37.79597], [-122.407014,37.795587], [-122.406591,37.795697], [-122.406649,37.796027], [-122.40568,37.796152], [-122.405526,37.795292], [-122.404959,37.795337] ] ] }, "id": "94108", "properties": { "id": "94108", "neighborhood": "Chinatown" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.420432,37.808308], [-122.420342,37.807746], [-122.420746,37.807598], [-122.419084,37.807804], [-122.418879,37.806877], [-122.4196,37.806783], [-122.418789,37.806249], [-122.418349,37.804101], [-122.418468,37.804109], [-122.418129,37.803168], [-122.417893,37.80172], [-122.419167,37.801559], [-122.419075,37.801144], [-122.417814,37.80132], [-122.417548,37.799967], [-122.418252,37.799884], [-122.418226,37.799295], [-122.41741,37.799405], [-122.417224,37.798494], [-122.415574,37.798688], [-122.413931,37.79047], [-122.41229,37.790669], [-122.411712,37.78787], [-122.413356,37.787657], [-122.413165,37.786726], [-122.414805,37.786523], [-122.414256,37.783728], [-122.427427,37.782055], [-122.430001,37.794906], [-122.423491,37.795723], [-122.42553,37.805821], [-122.425374,37.806107], [-122.425397,37.806565], [-122.426352,37.807528], [-122.425528,37.806976], [-122.424292,37.806622], [-122.423469,37.80678], [-122.422145,37.80759], [-122.421381,37.808188], [-122.42109,37.808549], [-122.421123,37.808812], [-122.422852,37.810176], [-122.422752,37.810251], [-122.421319,37.809178], [-122.421194,37.809232], [-122.420906,37.808818], [-122.420739,37.808837], [-122.420764,37.809105], [-122.420323,37.809002], [-122.420639,37.80884], [-122.42032,37.808739], [-122.420514,37.808645], [-122.420432,37.808308] ] ] }, "id": "94109", "properties": { "id": 94109, "neighborhood": "Nob Hill" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.420701,37.731936], [-122.420551,37.731562], [-122.420949,37.731304], [-122.420182,37.731449], [-122.420306,37.729926], [-122.420399,37.729529], [-122.420599,37.729374], [-122.422911,37.729289], [-122.423689,37.729515], [-122.426026,37.729391], [-122.426016,37.728636], [-122.423712,37.728761], [-122.423154,37.727262], [-122.424157,37.725984], [-122.423554,37.725625], [-122.422873,37.723983], [-122.424475,37.723544], [-122.425246,37.722277], [-122.424405,37.721949], [-122.425484,37.720235], [-122.423682,37.719801], [-122.423493,37.719533], [-122.423541,37.718906], [-122.423308,37.718471], [-122.422477,37.717882], [-122.423615,37.71719], [-122.424422,37.717063], [-122.425093,37.717356], [-122.425602,37.718097], [-122.42605,37.718375], [-122.427306,37.715611], [-122.42836,37.716053], [-122.431213,37.716631], [-122.433751,37.713118], [-122.42923,37.712203], [-122.426175,37.710959], [-122.427347,37.710021], [-122.427285,37.708352], [-122.433961,37.708232], [-122.435558,37.70799], [-122.436272,37.708244], [-122.440646,37.708221], [-122.441103,37.708333], [-122.442024,37.708085], [-122.44211,37.708251], [-122.44981,37.708246], [-122.449854,37.708358], [-122.450204,37.708242], [-122.454386,37.708221], [-122.455966,37.708386], [-122.45716,37.708221], [-122.458838,37.708437], [-122.459901,37.708244], [-122.469004,37.708187], [-122.46745,37.709496], [-122.465786,37.710243], [-122.464028,37.710549], [-122.460894,37.710579], [-122.462503,37.711207], [-122.462598,37.711377], [-122.462562,37.713806], [-122.462758,37.714264], [-122.462626,37.714469], [-122.46268,37.720018], [-122.462264,37.720021], [-122.46227,37.72527], [-122.462838,37.725488], [-122.462587,37.727158], [-122.462888,37.728087], [-122.462066,37.728095], [-122.460858,37.728754], [-122.460039,37.728777], [-122.459911,37.729952], [-122.459585,37.730425], [-122.459231,37.730582], [-122.459245,37.730838], [-122.458191,37.73088], [-122.454427,37.731533], [-122.444271,37.731596], [-122.444304,37.728562], [-122.444115,37.7283], [-122.443605,37.728313], [-122.439982,37.729929], [-122.435069,37.731505], [-122.433944,37.732408], [-122.428578,37.735082], [-122.427849,37.734718], [-122.426983,37.735455], [-122.422133,37.735162], [-122.422243,37.734846], [-122.422901,37.734388], [-122.421827,37.732917], [-122.421889,37.732533], [-122.422997,37.732224], [-122.423493,37.732317], [-122.4237,37.732172], [-122.425256,37.732125], [-122.425944,37.731698], [-122.423718,37.73155], [-122.420701,37.731936] ] ] }, "id": "94112", "properties": { "id": 94112, "neighborhood": "Ingleside" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.42828,37.769641], [-122.428262,37.769541], [-122.426242,37.769644], [-122.426896,37.769009], [-122.424928,37.748628], [-122.438168,37.747841], [-122.438259,37.748644], [-122.441209,37.748622], [-122.441851,37.748537], [-122.442512,37.748218], [-122.44399,37.746777], [-122.444318,37.747004], [-122.444685,37.746982], [-122.444081,37.747453], [-122.44411,37.74842], [-122.44345,37.749502], [-122.44273,37.752373], [-122.442509,37.75242], [-122.441838,37.753439], [-122.441256,37.753916], [-122.440108,37.755715], [-122.440154,37.756433], [-122.441013,37.756239], [-122.441426,37.756562], [-122.442224,37.756707], [-122.441394,37.756449], [-122.441139,37.756211], [-122.442884,37.755494], [-122.443334,37.75639], [-122.444617,37.757198], [-122.445648,37.757231], [-122.446474,37.757533], [-122.446912,37.757892], [-122.447093,37.757671], [-122.447003,37.75746], [-122.445905,37.756932], [-122.44605,37.756429], [-122.445121,37.756601], [-122.444679,37.756524], [-122.444373,37.756212], [-122.44423,37.755714], [-122.44423,37.755536], [-122.444746,37.755293], [-122.444639,37.754422], [-122.445121,37.75366], [-122.445427,37.75266], [-122.445085,37.751871], [-122.445069,37.751444], [-122.445288,37.750918], [-122.445771,37.750465], [-122.445935,37.750721], [-122.445661,37.751657], [-122.446088,37.752524], [-122.446427,37.752725], [-122.446108,37.753046], [-122.445997,37.753716], [-122.447214,37.754064], [-122.447519,37.753835], [-122.44743,37.754333], [-122.448641,37.754793], [-122.449441,37.755474], [-122.449611,37.756321], [-122.450168,37.756772], [-122.452095,37.756675], [-122.452084,37.756971], [-122.452354,37.757054], [-122.453279,37.7567], [-122.45409,37.757114], [-122.453759,37.757568], [-122.453158,37.757986], [-122.451348,37.75859], [-122.451531,37.759473], [-122.448095,37.759665], [-122.447637,37.759222], [-122.447468,37.759318], [-122.447146,37.75969], [-122.446481,37.76113], [-122.44679,37.761792], [-122.445302,37.761876], [-122.443776,37.763352], [-122.443017,37.76351], [-122.442944,37.764111], [-122.443207,37.764522], [-122.443242,37.765229], [-122.443426,37.765368], [-122.44122,37.765314], [-122.439489,37.766572], [-122.438575,37.766771], [-122.438094,37.766709], [-122.43819,37.767203], [-122.436477,37.767293], [-122.436632,37.769031], [-122.429137,37.769452], [-122.429208,37.770372], [-122.42828,37.769641] ] ] }, "id": "94114", "properties": { "id": "94114", "neighborhood": "Castro" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.456648,37.763844], [-122.46085,37.762616], [-122.46065,37.760577], [-122.46179,37.760505], [-122.461766,37.760113], [-122.461619,37.759868], [-122.461341,37.759789], [-122.46069,37.760089], [-122.460528,37.759536], [-122.462483,37.759342], [-122.462935,37.75906], [-122.463213,37.75861], [-122.462755,37.756882], [-122.463648,37.756636], [-122.463559,37.755159], [-122.463826,37.753998], [-122.463714,37.753509], [-122.463247,37.75286], [-122.467947,37.752765], [-122.46821,37.752963], [-122.468791,37.754241], [-122.469991,37.754686], [-122.470471,37.753431], [-122.469909,37.752784], [-122.470711,37.752359], [-122.470866,37.752536], [-122.473168,37.752564], [-122.508181,37.750987], [-122.507941,37.749124], [-122.50849,37.749138], [-122.509105,37.749743], [-122.509928,37.749936], [-122.509922,37.7502], [-122.510421,37.750956], [-122.510753,37.752401], [-122.510919,37.752598], [-122.511003,37.754535], [-122.51121,37.755586], [-122.510919,37.756636], [-122.511875,37.760314], [-122.511958,37.762154], [-122.512332,37.763007], [-122.512194,37.764109], [-122.512489,37.764633], [-122.513273,37.771077], [-122.511322,37.771173], [-122.511398,37.771486], [-122.510968,37.771331], [-122.47172,37.773141], [-122.471785,37.772681], [-122.472237,37.77236], [-122.474834,37.772518], [-122.478552,37.772254], [-122.479118,37.772006], [-122.479409,37.771509], [-122.479165,37.770749], [-122.476909,37.771533], [-122.475216,37.771681], [-122.47378,37.771182], [-122.474249,37.771029], [-122.475898,37.771087], [-122.476249,37.770754], [-122.476205,37.770261], [-122.475251,37.770068], [-122.47402,37.769507], [-122.471528,37.769845], [-122.471438,37.769604], [-122.472672,37.768601], [-122.472844,37.767756], [-122.472697,37.767444], [-122.472231,37.768606], [-122.471411,37.769112], [-122.470265,37.769228], [-122.469282,37.769118], [-122.466956,37.768001], [-122.464536,37.769638], [-122.461874,37.770266], [-122.460096,37.770396], [-122.459502,37.770711], [-122.459148,37.771316], [-122.462072,37.771779], [-122.464749,37.772486], [-122.465845,37.772545], [-122.465887,37.773401], [-122.454676,37.774758], [-122.452974,37.766367], [-122.456862,37.765856], [-122.457805,37.765978], [-122.457707,37.764705], [-122.457575,37.764847], [-122.456778,37.764938], [-122.456648,37.763844] ] ] }, "id": "94122", "properties": { "id": "94122", "neighborhood": "Sunset" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.380089,37.752759], [-122.380062,37.752064], [-122.376159,37.752283], [-122.375723,37.74872], [-122.376358,37.748638], [-122.376356,37.747159], [-122.375057,37.746841], [-122.374811,37.746423], [-122.374965,37.745818], [-122.374157,37.745048], [-122.373929,37.745014], [-122.373374,37.745414], [-122.372797,37.745573], [-122.367633,37.740199], [-122.368216,37.739935], [-122.373216,37.73973], [-122.373243,37.739554], [-122.373234,37.739297], [-122.372406,37.739007], [-122.36792,37.739216], [-122.372423,37.738953], [-122.373303,37.739284], [-122.373379,37.739718], [-122.374008,37.739622], [-122.374066,37.739462], [-122.373496,37.738645], [-122.372685,37.738317], [-122.367541,37.73834], [-122.367579,37.738218], [-122.370108,37.737729], [-122.371392,37.737134], [-122.372328,37.737065], [-122.373574,37.737233], [-122.374046,37.737409], [-122.374481,37.737844], [-122.375282,37.738105], [-122.375371,37.736427], [-122.376029,37.735769], [-122.376156,37.735123], [-122.375315,37.735416], [-122.374946,37.734928], [-122.375011,37.734747], [-122.375334,37.734633], [-122.375053,37.734363], [-122.375048,37.734148], [-122.375549,37.733124], [-122.374324,37.732569], [-122.373714,37.732963], [-122.372437,37.734205], [-122.37215,37.734273], [-122.370831,37.733231], [-122.370126,37.733662], [-122.370067,37.733579], [-122.370758,37.733162], [-122.369578,37.732404], [-122.369375,37.732034], [-122.368745,37.731968], [-122.368337,37.732254], [-122.367411,37.731931], [-122.366864,37.732334], [-122.366683,37.732285], [-122.36527,37.73386], [-122.365183,37.73375], [-122.366567,37.732159], [-122.365638,37.731617], [-122.364783,37.7326], [-122.365096,37.732096], [-122.363719,37.731331], [-122.362922,37.732232], [-122.362608,37.732045], [-122.363442,37.731154], [-122.362856,37.730839], [-122.362059,37.731724], [-122.361774,37.731576], [-122.362569,37.730661], [-122.36196,37.730325], [-122.362054,37.730155], [-122.360898,37.729983], [-122.36075,37.730276], [-122.36,37.730379], [-122.35887,37.729814], [-122.358962,37.72958], [-122.362149,37.728811], [-122.36226,37.728532], [-122.361816,37.728518], [-122.357767,37.72947], [-122.357503,37.729286], [-122.357846,37.729008], [-122.36006,37.728502], [-122.360449,37.728261], [-122.359967,37.728224], [-122.357272,37.728832], [-122.357031,37.728693], [-122.357735,37.726304], [-122.358027,37.726114], [-122.361677,37.725257], [-122.361297,37.724209], [-122.357944,37.724993], [-122.357849,37.724678], [-122.361434,37.723926], [-122.364857,37.726094], [-122.365156,37.725974], [-122.36501,37.725725], [-122.362287,37.723914], [-122.362707,37.723498], [-122.360005,37.721674], [-122.360273,37.721388], [-122.363043,37.72303], [-122.363836,37.722158], [-122.359153,37.719359], [-122.359931,37.718502], [-122.36272,37.720107], [-122.363655,37.719096], [-122.362576,37.718466], [-122.362678,37.718312], [-122.358611,37.715909], [-122.35875,37.715777], [-122.362668,37.718056], [-122.363859,37.716766], [-122.359959,37.71448], [-122.360097,37.71437], [-122.363988,37.716612], [-122.365229,37.715388], [-122.365229,37.715249], [-122.361115,37.712882], [-122.361226,37.712794], [-122.365443,37.715293], [-122.364475,37.716341], [-122.364642,37.716517], [-122.364892,37.716451], [-122.365336,37.71585], [-122.365513,37.715821], [-122.366008,37.716085], [-122.366426,37.716799], [-122.367697,37.717613], [-122.368134,37.717782], [-122.36953,37.717858], [-122.369955,37.71812], [-122.370353,37.718688], [-122.371784,37.719011], [-122.374191,37.718934], [-122.374317,37.719602], [-122.374531,37.719878], [-122.375775,37.720586], [-122.376094,37.721673], [-122.376073,37.722751], [-122.376755,37.723458], [-122.376818,37.724031], [-122.377564,37.724132], [-122.378863,37.723846], [-122.379928,37.722313], [-122.380731,37.72173], [-122.382591,37.72241], [-122.383777,37.723126], [-122.383999,37.723489], [-122.385167,37.72411], [-122.386436,37.724479], [-122.386835,37.724339], [-122.386911,37.724148], [-122.382843,37.721921], [-122.382765,37.721547], [-122.383381,37.720627], [-122.383253,37.720135], [-122.381696,37.71932], [-122.381353,37.718785], [-122.38058,37.718802], [-122.379724,37.71832], [-122.379915,37.71797], [-122.379807,37.717843], [-122.379217,37.717818], [-122.376187,37.716103], [-122.377399,37.714411], [-122.378896,37.713077], [-122.379684,37.711801], [-122.380004,37.711586], [-122.380035,37.710681], [-122.378821,37.710024], [-122.3783,37.709279], [-122.3783,37.708891], [-122.378012,37.708681], [-122.376979,37.70895], [-122.376436,37.7097], [-122.376085,37.70975], [-122.375571,37.709661], [-122.374625,37.70906], [-122.374427,37.708743], [-122.374662,37.708562], [-122.375646,37.708409], [-122.379472,37.708427], [-122.380428,37.708795], [-122.384507,37.709281], [-122.385965,37.709993], [-122.386977,37.709655], [-122.388155,37.708672], [-122.389693,37.709556], [-122.38991,37.70958], [-122.390654,37.709186], [-122.391782,37.709808], [-122.39094,37.710318], [-122.38874,37.710489], [-122.386724,37.711066], [-122.386375,37.711033], [-122.387684,37.712178], [-122.387994,37.713004], [-122.388774,37.71228], [-122.390439,37.712109], [-122.390961,37.712322], [-122.391224,37.713259], [-122.393041,37.713609], [-122.394738,37.713611], [-122.396527,37.714716], [-122.396489,37.714972], [-122.398027,37.715493], [-122.398393,37.716337], [-122.398555,37.717783], [-122.399202,37.71992], [-122.401262,37.724794], [-122.402107,37.727849], [-122.404946,37.733588], [-122.406506,37.735623], [-122.407024,37.738016], [-122.408009,37.737734], [-122.408136,37.73964], [-122.407045,37.739587], [-122.406936,37.740554], [-122.406652,37.741241], [-122.404524,37.744285], [-122.404865,37.744385], [-122.405493,37.744084], [-122.405614,37.7442], [-122.405091,37.745281], [-122.403798,37.749443], [-122.401546,37.74945], [-122.391705,37.750133], [-122.387666,37.750267], [-122.387833,37.752817], [-122.382933,37.753184], [-122.382078,37.753131], [-122.381482,37.752782], [-122.380089,37.752759] ] ] }, "id": "94124", "properties": { "id": "94124", "neighborhood": "Bayview" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.444271,37.731596], [-122.454427,37.731533], [-122.458191,37.73088], [-122.459245,37.730838], [-122.459231,37.730582], [-122.459585,37.730425], [-122.459911,37.729952], [-122.460039,37.728777], [-122.460858,37.728754], [-122.462066,37.728095], [-122.462888,37.728087], [-122.462587,37.727158], [-122.462838,37.725488], [-122.46227,37.72527], [-122.462297,37.723037], [-122.464104,37.722246], [-122.464475,37.721682], [-122.471815,37.721661], [-122.471677,37.720951], [-122.471654,37.71788], [-122.472453,37.717877], [-122.47226,37.721627], [-122.472667,37.721562], [-122.472676,37.722124], [-122.472602,37.724834], [-122.472364,37.726819], [-122.472829,37.726836], [-122.47269,37.728843], [-122.472283,37.728807], [-122.472046,37.733756], [-122.471751,37.733878], [-122.47168,37.734642], [-122.471464,37.734653], [-122.471543,37.7351], [-122.470664,37.736636], [-122.470972,37.737018], [-122.471224,37.741374], [-122.468572,37.741502], [-122.467798,37.743412], [-122.463662,37.743771], [-122.461372,37.745591], [-122.460766,37.745108], [-122.458701,37.74661], [-122.458952,37.746923], [-122.455093,37.746263], [-122.453776,37.745686], [-122.451731,37.745527], [-122.449493,37.743019], [-122.448814,37.742758], [-122.446663,37.742452], [-122.446266,37.742106], [-122.4461,37.741372], [-122.445874,37.741102], [-122.444651,37.740775], [-122.443888,37.740074], [-122.442865,37.739757], [-122.44256,37.739472], [-122.442635,37.738458], [-122.442409,37.737629], [-122.442603,37.737183], [-122.443662,37.736503], [-122.444158,37.736536], [-122.444385,37.736182], [-122.444704,37.736429], [-122.444598,37.737092], [-122.445914,37.737074], [-122.445737,37.736525], [-122.446381,37.73578], [-122.44633,37.735245], [-122.445366,37.734517], [-122.445397,37.734267], [-122.44573,37.733938], [-122.445652,37.733835], [-122.444319,37.733831], [-122.444271,37.731596] ] ] }, "id": "94127", "properties": { "id": 94127, "neighborhood": "Portola" }, "type": "Feature" }, { "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [-122.486279,37.736821], [-122.485731,37.736825], [-122.484755,37.737207], [-122.482882,37.737513], [-122.481446,37.737249], [-122.47097,37.737652], [-122.470945,37.736905], [-122.470664,37.736636], [-122.471543,37.7351], [-122.471464,37.734653], [-122.47168,37.734642], [-122.471751,37.733878], [-122.472046,37.733756], [-122.472283,37.728807], [-122.47269,37.728843], [-122.472829,37.726836], [-122.472364,37.726819], [-122.472602,37.724834], [-122.472676,37.722124], [-122.472667,37.721562], [-122.47226,37.721627], [-122.472453,37.717877], [-122.471654,37.71788], [-122.471677,37.720951], [-122.471815,37.721661], [-122.464475,37.721682], [-122.464104,37.722246], [-122.462297,37.723037], [-122.462264,37.720021], [-122.46268,37.720018], [-122.462626,37.714469], [-122.462758,37.714264], [-122.462562,37.713806], [-122.462598,37.711377], [-122.462503,37.711207], [-122.460894,37.710579], [-122.464028,37.710549], [-122.465786,37.710243], [-122.46745,37.709496], [-122.469004,37.708187], [-122.471987,37.708406], [-122.485555,37.70826], [-122.485383,37.708507], [-122.485717,37.70826], [-122.50278,37.70805], [-122.503255,37.709186], [-122.503881,37.712656], [-122.504632,37.714564], [-122.504809,37.715626], [-122.505174,37.716546], [-122.505394,37.718032], [-122.506133,37.720154], [-122.506222,37.721235], [-122.506473,37.721616], [-122.506687,37.723115], [-122.507043,37.72379], [-122.507151,37.72527], [-122.507551,37.72704], [-122.507223,37.72862], [-122.508116,37.731333], [-122.507951,37.732438], [-122.508526,37.733837], [-122.508172,37.73443], [-122.508396,37.734631], [-122.50842,37.735401], [-122.508573,37.735638], [-122.507884,37.735942], [-122.506807,37.735587], [-122.502009,37.735517], [-122.500874,37.735256], [-122.498765,37.734264], [-122.497435,37.733934], [-122.493786,37.733991], [-122.49343,37.734328], [-122.492622,37.734039], [-122.491528,37.734094], [-122.491263,37.734165], [-122.491357,37.735345], [-122.490312,37.735638], [-122.490714,37.736565], [-122.491319,37.737325], [-122.490655,37.737821], [-122.489989,37.737975], [-122.488812,37.73713], [-122.486279,37.736821] ] ] ] }, "id": "94132", "properties": { "id": 94132, "neighborhood": "Lake Merced" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.452936,37.7581], [-122.453759,37.757568], [-122.45409,37.757114], [-122.453279,37.7567], [-122.452354,37.757054], [-122.452084,37.756971], [-122.452095,37.756675], [-122.450168,37.756772], [-122.449611,37.756321], [-122.449441,37.755474], [-122.448641,37.754793], [-122.44743,37.754333], [-122.447519,37.753835], [-122.447214,37.754064], [-122.445997,37.753716], [-122.446108,37.753046], [-122.446427,37.752725], [-122.446088,37.752524], [-122.445661,37.751657], [-122.445935,37.750721], [-122.445771,37.750465], [-122.445288,37.750918], [-122.445069,37.751444], [-122.445085,37.751871], [-122.445427,37.75266], [-122.445121,37.75366], [-122.444639,37.754422], [-122.444746,37.755293], [-122.44423,37.755536], [-122.44423,37.755714], [-122.444373,37.756212], [-122.444679,37.756524], [-122.445121,37.756601], [-122.44605,37.756429], [-122.445905,37.756932], [-122.447003,37.75746], [-122.447093,37.757671], [-122.446912,37.757892], [-122.446474,37.757533], [-122.445648,37.757231], [-122.444617,37.757198], [-122.443334,37.75639], [-122.442884,37.755494], [-122.441139,37.756211], [-122.441394,37.756449], [-122.442072,37.756597], [-122.442224,37.756707], [-122.441426,37.756562], [-122.441013,37.756239], [-122.440154,37.756433], [-122.440108,37.755715], [-122.441256,37.753916], [-122.441838,37.753439], [-122.442509,37.75242], [-122.44273,37.752373], [-122.44345,37.749502], [-122.44411,37.74842], [-122.444081,37.747453], [-122.444685,37.746982], [-122.444318,37.747004], [-122.44399,37.746777], [-122.442512,37.748218], [-122.441851,37.748537], [-122.441092,37.748632], [-122.438259,37.748644], [-122.438168,37.747841], [-122.424928,37.748628], [-122.424168,37.740805], [-122.424394,37.740405], [-122.42427,37.739867], [-122.42452,37.739868], [-122.42551,37.737774], [-122.428454,37.735882], [-122.42801,37.735441], [-122.433944,37.732408], [-122.435069,37.731505], [-122.439982,37.729929], [-122.443605,37.728313], [-122.444115,37.7283], [-122.444304,37.728562], [-122.444319,37.733831], [-122.445652,37.733835], [-122.44573,37.733938], [-122.445397,37.734267], [-122.445366,37.734517], [-122.44633,37.735245], [-122.446387,37.735748], [-122.445737,37.736525], [-122.445914,37.737074], [-122.444598,37.737092], [-122.444704,37.736429], [-122.444385,37.736182], [-122.444158,37.736536], [-122.443662,37.736503], [-122.442523,37.737263], [-122.442409,37.737629], [-122.442628,37.738387], [-122.442523,37.739283], [-122.442631,37.739589], [-122.443888,37.740074], [-122.444651,37.740775], [-122.445874,37.741102], [-122.4461,37.741372], [-122.446266,37.742106], [-122.446663,37.742452], [-122.448814,37.742758], [-122.449493,37.743019], [-122.451731,37.745527], [-122.453776,37.745686], [-122.455093,37.746263], [-122.458952,37.746923], [-122.45919,37.747199], [-122.458708,37.747608], [-122.458717,37.748113], [-122.460528,37.749935], [-122.461227,37.751194], [-122.463247,37.75286], [-122.46379,37.753707], [-122.463554,37.75526], [-122.463648,37.756636], [-122.462755,37.756882], [-122.463213,37.75861], [-122.462935,37.75906], [-122.462483,37.759342], [-122.460528,37.759536], [-122.46069,37.760089], [-122.461341,37.759789], [-122.461619,37.759868], [-122.461766,37.760113], [-122.46179,37.760505], [-122.46065,37.760577], [-122.46085,37.762616], [-122.455731,37.764099], [-122.455465,37.760271], [-122.453594,37.761617], [-122.452405,37.761578], [-122.45182,37.758743], [-122.452997,37.758202], [-122.452936,37.7581] ] ] }, "id": "94131", "properties": { "id": 94131, "neighborhood": "Twin Peaks" }, "type": "Feature" }, { "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [-122.419083,37.811572], [-122.415375,37.809166], [-122.415194,37.809226], [-122.415403,37.809424], [-122.415085,37.809231], [-122.414794,37.809331], [-122.415315,37.809767], [-122.415212,37.809848], [-122.413444,37.809247], [-122.413371,37.809391], [-122.414276,37.809863], [-122.414024,37.81014], [-122.413789,37.809946], [-122.413868,37.809874], [-122.412638,37.809089], [-122.41239,37.809118], [-122.411911,37.809384], [-122.412856,37.810523], [-122.412717,37.810604], [-122.411402,37.809035], [-122.41056,37.808843], [-122.410475,37.80937], [-122.411323,37.810958], [-122.410669,37.811379], [-122.410203,37.811311], [-122.409973,37.810966], [-122.410179,37.810095], [-122.409611,37.809141], [-122.409242,37.809049], [-122.409109,37.808848], [-122.409089,37.808138], [-122.405774,37.806775], [-122.405899,37.806399], [-122.405462,37.806107], [-122.405175,37.804795], [-122.40596,37.80469], [-122.405752,37.803725], [-122.404953,37.803822], [-122.405067,37.802885], [-122.403175,37.803098], [-122.402791,37.801265], [-122.4036,37.801195], [-122.403549,37.800548], [-122.404359,37.800576], [-122.404329,37.800423], [-122.404265,37.80013], [-122.403422,37.800209], [-122.403765,37.799746], [-122.403656,37.799212], [-122.402423,37.799369], [-122.401864,37.796638], [-122.405152,37.796213], [-122.404959,37.795337], [-122.405526,37.795292], [-122.40568,37.796152], [-122.406649,37.796027], [-122.406591,37.795697], [-122.407014,37.795587], [-122.407091,37.79597], [-122.411087,37.795467], [-122.411024,37.795145], [-122.411484,37.795033], [-122.411553,37.795409], [-122.414883,37.79503], [-122.415574,37.798688], [-122.417224,37.798494], [-122.41741,37.799405], [-122.418226,37.799295], [-122.418252,37.799884], [-122.417548,37.799967], [-122.417814,37.80132], [-122.419075,37.801144], [-122.419167,37.801559], [-122.417893,37.80172], [-122.418129,37.803168], [-122.418468,37.804109], [-122.418349,37.804101], [-122.418789,37.806249], [-122.4196,37.806783], [-122.418879,37.806877], [-122.419084,37.807804], [-122.420746,37.807598], [-122.420342,37.807746], [-122.420432,37.808308], [-122.417911,37.808629], [-122.417992,37.808864], [-122.419957,37.808915], [-122.41998,37.809133], [-122.418052,37.809139], [-122.417879,37.808993], [-122.417733,37.808362], [-122.417454,37.80838], [-122.417364,37.808135], [-122.4164,37.808303], [-122.416315,37.808478], [-122.4172,37.808528], [-122.416291,37.808576], [-122.416241,37.808862], [-122.417477,37.808903], [-122.417448,37.809198], [-122.420591,37.811315], [-122.420379,37.811535], [-122.418938,37.810817], [-122.419471,37.811444], [-122.419083,37.811572] ] ] ] }, "id": "94133", "properties": { "id": "94133", "neighborhood": "North Beach" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.405883,37.785718], [-122.426242,37.769644], [-122.428262,37.769541], [-122.429573,37.776045], [-122.4294,37.776267], [-122.429593,37.776526], [-122.429983,37.778864], [-122.426829,37.779265], [-122.427427,37.782055], [-122.414256,37.783728], [-122.414805,37.786523], [-122.413165,37.786726], [-122.413356,37.787657], [-122.411712,37.78787], [-122.411913,37.788812], [-122.408655,37.789244], [-122.408244,37.787369], [-122.406602,37.787583], [-122.406236,37.785793], [-122.405883,37.785718] ] ] }, "id": "94102", "properties": { "id": 94102, "neighborhood": "Tenderloin" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.398941,37.783785], [-122.405629,37.778502], [-122.399425,37.773612], [-122.403723,37.770182], [-122.404003,37.77018], [-122.403477,37.769842], [-122.402105,37.769912], [-122.402091,37.769716], [-122.401685,37.769721], [-122.401768,37.769145], [-122.402021,37.768998], [-122.401851,37.767416], [-122.400881,37.767518], [-122.400915,37.768096], [-122.40001,37.767614], [-122.400422,37.767291], [-122.3998,37.766807], [-122.399688,37.765005], [-122.407431,37.764497], [-122.407553,37.765798], [-122.419459,37.765089], [-122.421248,37.764947], [-122.421031,37.76335], [-122.42173,37.763304], [-122.421885,37.764908], [-122.426453,37.764634], [-122.426897,37.769107], [-122.42245,37.772761], [-122.403427,37.787676], [-122.40333,37.787336], [-122.401497,37.785824], [-122.39999,37.787004], [-122.399523,37.786631], [-122.400955,37.785389], [-122.398941,37.783785] ] ] }, "id": "94103", "properties": { "id": 94103, "neighborhood": "SoMa" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.405115,37.764635], [-122.405212,37.763469], [-122.405832,37.762199], [-122.405859,37.761815], [-122.40604,37.761865], [-122.406365,37.761199], [-122.40645,37.760114], [-122.406167,37.759315], [-122.406015,37.759409], [-122.405604,37.758851], [-122.40405,37.757619], [-122.403428,37.756871], [-122.403585,37.756818], [-122.403328,37.756082], [-122.40315,37.754488], [-122.403524,37.754463], [-122.403437,37.753199], [-122.403364,37.752366], [-122.403022,37.752336], [-122.403052,37.752048], [-122.405091,37.745281], [-122.405614,37.7442], [-122.405493,37.744084], [-122.404865,37.744385], [-122.404524,37.744285], [-122.406652,37.741241], [-122.406936,37.740554], [-122.407045,37.739587], [-122.408136,37.73964], [-122.408009,37.737734], [-122.408218,37.73765], [-122.408284,37.736846], [-122.408613,37.736074], [-122.409287,37.735258], [-122.410052,37.734675], [-122.411978,37.733732], [-122.412695,37.733197], [-122.414554,37.732371], [-122.416255,37.732034], [-122.419881,37.732016], [-122.423718,37.73155], [-122.425944,37.731698], [-122.425256,37.732125], [-122.422274,37.732383], [-122.421889,37.732533], [-122.421787,37.732774], [-122.422472,37.733967], [-122.422901,37.734388], [-122.422243,37.734846], [-122.422133,37.735162], [-122.426983,37.735455], [-122.427849,37.734718], [-122.428578,37.735082], [-122.42801,37.735441], [-122.428454,37.735882], [-122.42551,37.737774], [-122.42452,37.739868], [-122.42427,37.739867], [-122.424394,37.740405], [-122.424168,37.740805], [-122.426453,37.764634], [-122.421885,37.764908], [-122.42173,37.763304], [-122.421031,37.76335], [-122.421248,37.764947], [-122.407553,37.765798], [-122.407431,37.764497], [-122.405115,37.764635] ] ] }, "id": "94110", "properties": { "id": 94110, "neighborhood": "Mission" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.391701,37.794113], [-122.392429,37.793835], [-122.393875,37.795248], [-122.399156,37.791051], [-122.399607,37.791317], [-122.400146,37.79415], [-122.404629,37.79358], [-122.405152,37.796213], [-122.401864,37.796638], [-122.402423,37.799369], [-122.403656,37.799212], [-122.403765,37.799746], [-122.403422,37.800209], [-122.404265,37.80013], [-122.404329,37.800423], [-122.404359,37.800576], [-122.403549,37.800548], [-122.4036,37.801195], [-122.402791,37.801265], [-122.403175,37.803098], [-122.405067,37.802885], [-122.404953,37.803822], [-122.405752,37.803725], [-122.40596,37.80469], [-122.405175,37.804795], [-122.405462,37.806107], [-122.405899,37.806399], [-122.405774,37.806775], [-122.409089,37.808138], [-122.409004,37.808563], [-122.407936,37.808146], [-122.407617,37.808244], [-122.407477,37.808085], [-122.406554,37.807891], [-122.406816,37.810064], [-122.406209,37.810103], [-122.405976,37.807252], [-122.405313,37.806883], [-122.404321,37.808927], [-122.403972,37.808829], [-122.404712,37.807015], [-122.403955,37.806592], [-122.402774,37.808053], [-122.402375,37.807896], [-122.403406,37.806516], [-122.402824,37.806076], [-122.400944,37.807679], [-122.400408,37.807307], [-122.40097,37.803579], [-122.400512,37.8035], [-122.39855,37.80465], [-122.398217,37.804315], [-122.399938,37.803283], [-122.399597,37.802882], [-122.397818,37.803862], [-122.397518,37.803526], [-122.399718,37.802209], [-122.399419,37.801867], [-122.399203,37.801906], [-122.397115,37.803089], [-122.39613,37.801975], [-122.3984,37.80072], [-122.398001,37.800267], [-122.395772,37.801535], [-122.39544,37.80118], [-122.397667,37.7999], [-122.396766,37.798884], [-122.39658,37.798852], [-122.394503,37.800155], [-122.394306,37.80013], [-122.394252,37.799996], [-122.396516,37.798686], [-122.395855,37.797941], [-122.395655,37.797922], [-122.393825,37.798956], [-122.393551,37.798652], [-122.395468,37.797463], [-122.395024,37.797575], [-122.394882,37.797427], [-122.39512,37.797145], [-122.393219,37.798276], [-122.392969,37.797941], [-122.394774,37.796778], [-122.394682,37.796659], [-122.3942,37.796922], [-122.393041,37.795634], [-122.391593,37.796229], [-122.391211,37.795822], [-122.392391,37.794856], [-122.392292,37.794737], [-122.391934,37.794842], [-122.391668,37.79458], [-122.391934,37.794376], [-122.391701,37.794113] ] ] }, "id": "94111", "properties": { "id": 94111, "neighborhood": "Financial District" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.427427,37.782055], [-122.426829,37.779265], [-122.444972,37.776956], [-122.445357,37.778831], [-122.446084,37.778731], [-122.446307,37.77984], [-122.446226,37.780051], [-122.44544,37.780142], [-122.445536,37.781341], [-122.447476,37.781067], [-122.447533,37.781349], [-122.447238,37.782464], [-122.44584,37.782546], [-122.447689,37.791703], [-122.446306,37.791871], [-122.446428,37.792795], [-122.44153,37.793428], [-122.441719,37.794387], [-122.440875,37.794492], [-122.440679,37.793537], [-122.430001,37.794906], [-122.427427,37.782055] ] ] }, "id": "94115", "properties": { "id": 94115, "neighborhood": "Lower Pacific Heights" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.463247,37.75286], [-122.461338,37.751312], [-122.460528,37.749935], [-122.458717,37.748113], [-122.458708,37.747608], [-122.45919,37.747199], [-122.458701,37.74661], [-122.460766,37.745108], [-122.461372,37.745591], [-122.463662,37.743771], [-122.467798,37.743412], [-122.468572,37.741502], [-122.471224,37.741374], [-122.47097,37.737652], [-122.481446,37.737249], [-122.482882,37.737513], [-122.486168,37.736807], [-122.488812,37.73713], [-122.489989,37.737975], [-122.490655,37.737821], [-122.491319,37.737325], [-122.490714,37.736565], [-122.490312,37.735638], [-122.491357,37.735345], [-122.491263,37.734165], [-122.491528,37.734094], [-122.492622,37.734039], [-122.49343,37.734328], [-122.493786,37.733991], [-122.497435,37.733934], [-122.498765,37.734264], [-122.500874,37.735256], [-122.502009,37.735517], [-122.506807,37.735587], [-122.507884,37.735942], [-122.508573,37.735638], [-122.50817,37.736602], [-122.50842,37.739587], [-122.508233,37.740381], [-122.509089,37.74456], [-122.508879,37.74557], [-122.509589,37.747897], [-122.50961,37.748912], [-122.509928,37.749936], [-122.509105,37.749743], [-122.50849,37.749138], [-122.507941,37.749124], [-122.508181,37.750987], [-122.473168,37.752564], [-122.470866,37.752536], [-122.470711,37.752359], [-122.469909,37.752784], [-122.470471,37.753431], [-122.469991,37.754686], [-122.468791,37.754241], [-122.46821,37.752963], [-122.467947,37.752765], [-122.463247,37.75286] ] ] }, "id": "94116", "properties": { "id": "94116", "neighborhood": "Taraval" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.42828,37.769641], [-122.429208,37.770372], [-122.429137,37.769452], [-122.436632,37.769031], [-122.436477,37.767293], [-122.43819,37.767203], [-122.438094,37.766709], [-122.438575,37.766771], [-122.439489,37.766572], [-122.44122,37.765314], [-122.443426,37.765368], [-122.443242,37.765229], [-122.443207,37.764522], [-122.442944,37.764111], [-122.443017,37.76351], [-122.443776,37.763352], [-122.445302,37.761876], [-122.44679,37.761792], [-122.446481,37.76113], [-122.447146,37.75969], [-122.447468,37.759318], [-122.447637,37.759222], [-122.448095,37.759665], [-122.451531,37.759473], [-122.451348,37.75859], [-122.452936,37.7581], [-122.452997,37.758202], [-122.45182,37.758743], [-122.452405,37.761578], [-122.453594,37.761617], [-122.455465,37.760271], [-122.455731,37.764099], [-122.456648,37.763844], [-122.456778,37.764938], [-122.457575,37.764847], [-122.457707,37.764705], [-122.457805,37.765978], [-122.456862,37.765856], [-122.452974,37.766367], [-122.454676,37.774758], [-122.452852,37.774986], [-122.453191,37.776877], [-122.446859,37.777678], [-122.446673,37.776733], [-122.429983,37.778864], [-122.429593,37.776526], [-122.4294,37.776267], [-122.429573,37.776045], [-122.42828,37.769641] ] ] }, "id": "94117", "properties": { "id": "94117", "neighborhood": "Panhandle" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.444972,37.776956], [-122.446673,37.776733], [-122.446859,37.777678], [-122.453191,37.776877], [-122.452852,37.774986], [-122.465887,37.773401], [-122.465845,37.772545], [-122.464749,37.772486], [-122.462072,37.771779], [-122.459148,37.771316], [-122.459502,37.770711], [-122.460096,37.770396], [-122.461874,37.770266], [-122.464536,37.769638], [-122.466956,37.768001], [-122.469006,37.769046], [-122.470813,37.769209], [-122.471557,37.769065], [-122.472056,37.768783], [-122.472362,37.7684], [-122.472697,37.767444], [-122.472844,37.767756], [-122.472672,37.768601], [-122.471497,37.76954], [-122.471476,37.769812], [-122.47402,37.769507], [-122.475251,37.770068], [-122.476153,37.770232], [-122.476281,37.770393], [-122.476217,37.770837], [-122.475898,37.771087], [-122.474249,37.771029], [-122.47378,37.771182], [-122.475395,37.771703], [-122.477216,37.77146], [-122.479165,37.770749], [-122.479412,37.771247], [-122.479254,37.771868], [-122.478613,37.772245], [-122.474834,37.772518], [-122.472407,37.772329], [-122.471937,37.772516], [-122.471729,37.772828], [-122.47172,37.773141], [-122.475639,37.772941], [-122.476602,37.78702], [-122.475083,37.787011], [-122.473321,37.787239], [-122.472691,37.786462], [-122.472522,37.787124], [-122.471777,37.787485], [-122.468463,37.787804], [-122.449327,37.791654], [-122.449368,37.791488], [-122.447689,37.791703], [-122.44584,37.782546], [-122.447238,37.782464], [-122.447533,37.781349], [-122.447476,37.781067], [-122.445536,37.781341], [-122.44544,37.780142], [-122.446226,37.780051], [-122.446307,37.77984], [-122.446084,37.778731], [-122.445357,37.778831], [-122.444972,37.776956] ] ] }, "id": "94118", "properties": { "id": "94118", "neighborhood": "Inner Richmond" }, "type": "Feature" }, { "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [-122.515568,37.778158], [-122.515522,37.778054], [-122.516044,37.778034], [-122.5171,37.778255], [-122.515972,37.778931], [-122.515659,37.778709], [-122.51575,37.778534], [-122.515568,37.778158] ] ], [ [ [-122.517686,37.780601], [-122.517402,37.780516], [-122.517389,37.780248], [-122.517109,37.780174], [-122.517043,37.779939], [-122.517474,37.779998], [-122.517747,37.78023], [-122.517686,37.780601] ] ], [ [ [-122.484717,37.789597], [-122.484583,37.789242], [-122.484718,37.788811], [-122.485334,37.788309], [-122.485284,37.787608], [-122.483795,37.787747], [-122.483607,37.78743], [-122.48337,37.78736], [-122.48138,37.787401], [-122.479785,37.787032], [-122.479129,37.787142], [-122.477715,37.786931], [-122.476602,37.78702], [-122.475639,37.772941], [-122.510968,37.771331], [-122.511398,37.771486], [-122.511322,37.771173], [-122.513273,37.771077], [-122.513184,37.774133], [-122.513026,37.774949], [-122.513142,37.775182], [-122.513194,37.777452], [-122.514068,37.778184], [-122.514289,37.778184], [-122.514373,37.77944], [-122.514926,37.779652], [-122.514884,37.779893], [-122.514399,37.780002], [-122.514178,37.780542], [-122.514736,37.781041], [-122.514698,37.781217], [-122.514205,37.781328], [-122.514245,37.781536], [-122.513721,37.781503], [-122.513795,37.781861], [-122.513426,37.782119], [-122.513563,37.782343], [-122.513395,37.782526], [-122.51349,37.782784], [-122.512869,37.782851], [-122.512785,37.783408], [-122.512406,37.783757], [-122.51267,37.784013], [-122.512121,37.783849], [-122.511811,37.783945], [-122.511632,37.784377], [-122.511411,37.784286], [-122.511348,37.784585], [-122.510833,37.784452], [-122.509747,37.784795], [-122.509062,37.785544], [-122.508124,37.785907], [-122.506904,37.787204], [-122.50621,37.787597], [-122.506022,37.787797], [-122.506092,37.788194], [-122.505811,37.78826], [-122.504845,37.787919], [-122.504094,37.788082], [-122.503578,37.787971], [-122.502917,37.788146], [-122.500674,37.788287], [-122.50006,37.788535], [-122.499835,37.788446], [-122.499703,37.788669], [-122.499497,37.788669], [-122.499037,37.788298], [-122.498381,37.788217], [-122.498118,37.787979], [-122.497677,37.787987], [-122.497246,37.78749], [-122.496326,37.78732], [-122.49486,37.78784], [-122.494599,37.788153], [-122.49389,37.787551], [-122.492867,37.787922], [-122.492545,37.787773], [-122.492055,37.787864], [-122.491482,37.788136], [-122.490012,37.789413], [-122.488188,37.789339], [-122.487051,37.789528], [-122.485863,37.790665], [-122.485131,37.790421], [-122.484717,37.789597] ] ] ] }, "id": "94121", "properties": { "id": "94121", "neighborhood": "Outer Richmond" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.426352,37.807528], [-122.425397,37.806565], [-122.425374,37.806107], [-122.42553,37.805821], [-122.423491,37.795723], [-122.440679,37.793537], [-122.440875,37.794492], [-122.441719,37.794387], [-122.44153,37.793428], [-122.446428,37.792795], [-122.447811,37.80152], [-122.448525,37.801634], [-122.449009,37.801917], [-122.449404,37.802357], [-122.449561,37.802801], [-122.449275,37.803858], [-122.448409,37.804394], [-122.448243,37.804788], [-122.448481,37.806062], [-122.448321,37.806876], [-122.447295,37.807455], [-122.443705,37.807725], [-122.441096,37.808198], [-122.44055,37.80839], [-122.440055,37.808821], [-122.439998,37.808663], [-122.44041,37.808174], [-122.441003,37.808088], [-122.441364,37.80786], [-122.441493,37.808019], [-122.442101,37.807966], [-122.442427,37.807869], [-122.442406,37.807668], [-122.44268,37.807623], [-122.44274,37.80782], [-122.442999,37.807803], [-122.443683,37.807592], [-122.443643,37.807467], [-122.447471,37.806461], [-122.44728,37.805577], [-122.447182,37.805402], [-122.442496,37.806008], [-122.442604,37.806591], [-122.444053,37.806469], [-122.442517,37.806758], [-122.442471,37.807123], [-122.442303,37.806809], [-122.435826,37.807598], [-122.435633,37.806878], [-122.434208,37.80697], [-122.433816,37.805671], [-122.432637,37.805729], [-122.432535,37.805917], [-122.432195,37.806011], [-122.432646,37.808535], [-122.432349,37.808561], [-122.432062,37.807246], [-122.431414,37.807326], [-122.431787,37.809057], [-122.431368,37.809109], [-122.431027,37.807395], [-122.430333,37.807473], [-122.430652,37.809196], [-122.430212,37.809257], [-122.429937,37.807873], [-122.428901,37.808021], [-122.428209,37.808373], [-122.427017,37.808129], [-122.427547,37.808655], [-122.428028,37.808617], [-122.428059,37.808747], [-122.427568,37.808804], [-122.426866,37.80813], [-122.426726,37.808158], [-122.426817,37.809302], [-122.426369,37.810186], [-122.425473,37.810746], [-122.424468,37.810765], [-122.424322,37.810603], [-122.424449,37.81045], [-122.424801,37.810665], [-122.425364,37.810603], [-122.425897,37.810359], [-122.426387,37.809852], [-122.426648,37.808866], [-122.426352,37.807528] ] ] }, "id": "94123", "properties": { "id": 94123, "neighborhood": "Marina" }, "type": "Feature" }, { "geometry": { "type": "Polygon", "coordinates": [ [ [-122.391527,37.709674], [-122.393396,37.708262], [-122.395354,37.708369], [-122.407491,37.708181], [-122.408326,37.708426], [-122.410318,37.708314], [-122.410071,37.708909], [-122.412248,37.708601], [-122.413821,37.709054], [-122.414165,37.708316], [-122.418198,37.708311], [-122.420305,37.707817], [-122.420709,37.708291], [-122.426074,37.708319], [-122.426415,37.707763], [-122.427043,37.708066], [-122.426985,37.70837], [-122.427283,37.708307], [-122.427347,37.710021], [-122.426175,37.710959], [-122.42923,37.712203], [-122.433751,37.713118], [-122.431213,37.716631], [-122.42836,37.716053], [-122.427306,37.715611], [-122.42605,37.718375], [-122.425602,37.718097], [-122.425093,37.717356], [-122.424422,37.717063], [-122.423615,37.71719], [-122.422477,37.717882], [-122.423308,37.718471], [-122.423541,37.718906], [-122.423493,37.719533], [-122.423682,37.719801], [-122.425484,37.720235], [-122.424405,37.721949], [-122.425246,37.722277], [-122.424475,37.723544], [-122.422873,37.723983], [-122.423554,37.725625], [-122.424157,37.725984], [-122.423154,37.727262], [-122.423712,37.728761], [-122.426016,37.728636], [-122.426026,37.729391], [-122.423689,37.729515], [-122.422911,37.729289], [-122.420599,37.729374], [-122.420399,37.729529], [-122.420306,37.729926], [-122.420182,37.731449], [-122.420949,37.731304], [-122.420551,37.731562], [-122.420701,37.731936], [-122.416255,37.732034], [-122.413909,37.732606], [-122.409647,37.734951], [-122.408488,37.736297], [-122.408218,37.73765], [-122.407024,37.738016], [-122.406506,37.735623], [-122.404946,37.733588], [-122.402107,37.727849], [-122.401262,37.724794], [-122.399202,37.71992], [-122.398555,37.717783], [-122.398393,37.716337], [-122.398027,37.715493], [-122.396489,37.714972], [-122.396527,37.714716], [-122.394738,37.713611], [-122.393041,37.713609], [-122.391224,37.713259], [-122.390961,37.712322], [-122.390439,37.712109], [-122.388774,37.71228], [-122.387994,37.713004], [-122.387684,37.712178], [-122.386375,37.711033], [-122.386724,37.711066], [-122.38874,37.710489], [-122.39094,37.710318], [-122.391782,37.709808], [-122.391527,37.709674] ] ] }, "id": "94134", "properties": { "id": 94134, "neighborhood": "Bayshore" }, "type": "Feature" } ] } ================================================ FILE: examples/.data/us-election-2016.json ================================================ [{"dem":2464364,"rep":769743,"total":3434308,"name":"Los Angeles, California","coordinates":[-118.26186,34.19639]}, {"dem":1611946,"rep":453287,"total":2158615,"name":"Cook, Illinois","coordinates":[-87.64545,41.89429]}, {"dem":702907,"rep":747361,"total":1567834,"name":"Maricopa, Arizona","coordinates":[-112.49892,33.34517]}, {"dem":707914,"rep":545955,"total":1312112,"name":"Harris, Texas","coordinates":[-95.39303,29.85727]}, {"dem":735476,"rep":477766,"total":1306400,"name":"San Diego, California","coordinates":[-116.77611,33.0236]}, {"dem":609961,"rep":507148,"total":1197521,"name":"Orange, California","coordinates":[-117.7772,33.67568]}, {"dem":718322,"rep":216339,"total":998499,"name":"King, Washington","coordinates":[-121.83399,47.49059]}, {"dem":624146,"rep":333999,"total":980204,"name":"Miami-Dade, Florida","coordinates":[-80.49709,25.61057]}, {"dem":553320,"rep":260951,"total":831951,"name":"Broward, Florida","coordinates":[-80.47668,26.19353]}, {"dem":640553,"rep":141044,"total":805605,"name":"Kings, New York","coordinates":[-73.95063,40.63504]}, {"dem":520360,"rep":219793,"total":784034,"name":"Middlesex, Massachusetts","coordinates":[-71.39491,42.48171]}, {"dem":519444,"rep":228993,"total":777838,"name":"Wayne, Michigan","coordinates":[-83.26195,42.28466]}, {"dem":402227,"rep":320057,"total":767156,"name":"Clark, Nevada","coordinates":[-115.01381,36.21425]}, {"dem":461080,"rep":262945,"total":758973,"name":"Dallas, Texas","coordinates":[-96.77842,32.76698]}, {"dem":373695,"rep":333243,"total":751391,"name":"Riverside, California","coordinates":[-116.00223,33.72982]}, {"dem":584025,"rep":108748,"total":707631,"name":"Philadelphia, Pennsylvania","coordinates":[-75.13334,40.00937]}, {"dem":511684,"rep":144826,"total":703709,"name":"Santa Clara, California","coordinates":[-121.6905,37.22069]}, {"dem":517220,"rep":149341,"total":686393,"name":"Queens, New York","coordinates":[-73.83801,40.65856]}, {"dem":303951,"rep":350570,"total":681254,"name":"Suffolk, New York","coordinates":[-72.69221,40.94355]}, {"dem":429288,"rep":191770,"total":679977,"name":"Hennepin, Minnesota","coordinates":[-93.47522,45.00612]}, {"dem":579013,"rep":64929,"total":668939,"name":"New York, New York","coordinates":[-73.97018,40.77664]}, {"dem":288392,"rep":345921,"total":668514,"name":"Tarrant, Texas","coordinates":[-97.29122,32.77211]}, {"dem":343070,"rep":289203,"total":664614,"name":"Oakland, Michigan","coordinates":[-83.38421,42.66045]}, {"dem":374673,"rep":272402,"total":662332,"name":"Palm Beach, Florida","coordinates":[-80.44835,26.64912]}, {"dem":514842,"rep":95922,"total":654266,"name":"Alameda, California","coordinates":[-121.91248,37.64713]}, {"dem":340833,"rep":271240,"total":653983,"name":"San Bernardino, California","coordinates":[-116.18119,34.85721]}, {"dem":367617,"rep":259480,"total":650114,"name":"Allegheny, Pennsylvania","coordinates":[-79.98045,40.46975]}, {"dem":326088,"rep":288313,"total":636967,"name":"Nassau, New York","coordinates":[-73.58941,40.72961]}, {"dem":398271,"rep":184211,"total":603822,"name":"Cuyahoga, Ohio","coordinates":[-81.72421,41.76039]}, {"dem":307896,"rep":266870,"total":597660,"name":"Hillsborough, Florida","coordinates":[-82.34971,27.9066]}, {"dem":319550,"rep":240333,"total":589645,"name":"Bexar, Texas","coordinates":[-98.52014,29.44867]}, {"dem":351198,"rep":199331,"total":581140,"name":"Franklin, Ohio","coordinates":[-83.00908,39.96987]}, {"dem":326023,"rep":189789,"total":559330,"name":"Sacramento, California","coordinates":[-121.34044,38.45001]}, {"dem":355133,"rep":157710,"total":551183,"name":"Fairfax, Virginia","coordinates":[-77.27325,38.82952]}, {"dem":329894,"rep":195216,"total":546275,"name":"Orange, Florida","coordinates":[-81.32328,28.51439]}, {"dem":302736,"rep":196082,"total":527624,"name":"Wake, North Carolina","coordinates":[-78.65062,35.78984]}, {"dem":286704,"rep":202434,"total":514858,"name":"St. Louis County, Missouri","coordinates":[-90.44607,38.64068]}, {"dem":233701,"rep":239201,"total":492403,"name":"Pinellas, Florida","coordinates":[-82.73951,27.9031]}, {"dem":357837,"rep":92704,"total":478873,"name":"Montgomery, Maryland","coordinates":[-77.20306,39.13738]}, {"dem":294562,"rep":155518,"total":472857,"name":"Mecklenburg, North Carolina","coordinates":[-80.83383,35.24686]}, {"dem":308260,"rep":127209,"total":468720,"name":"Travis, Texas","coordinates":[-97.69126,30.23951]}, {"dem":319287,"rep":115956,"total":466175,"name":"Contra Costa, California","coordinates":[-121.95154,37.91947]}, {"dem":288797,"rep":125846,"total":440247,"name":"Milwaukee, Wisconsin","coordinates":[-87.48155,43.01766]}, {"dem":256082,"rep":162731,"total":434687,"name":"Montgomery, Pennsylvania","coordinates":[-75.3702,40.20999]}, {"dem":205704,"rep":211672,"total":432695,"name":"Duval, Florida","coordinates":[-81.64811,30.33524]}, {"dem":297051,"rep":117783,"total":431391,"name":"Fulton, Georgia","coordinates":[-84.46818,33.79003]}, {"dem":228622,"rep":166415,"total":428769,"name":"DuPage, Illinois","coordinates":[-88.08603,41.85205]}, {"dem":215456,"rep":188303,"total":423625,"name":"Erie, New York","coordinates":[-78.77819,42.75275]}, {"dem":224661,"rep":167428,"total":421640,"name":"Pima, Arizona","coordinates":[-111.78365,32.12804]}, {"dem":243852,"rep":160077,"total":421209,"name":"Fairfield, Connecticut","coordinates":[-73.36706,41.22741]}, {"dem":272926,"rep":131238,"total":420655,"name":"Westchester, New York","coordinates":[-73.74575,41.15268]}, {"dem":176317,"rep":224665,"total":419312,"name":"Macomb, Michigan","coordinates":[-82.91145,42.67155]}, {"dem":231211,"rep":175529,"total":419296,"name":"Bergen, New Jersey","coordinates":[-74.07472,40.95969]}, {"dem":175863,"rep":138043,"total":418868,"name":"Salt Lake, Utah","coordinates":[-111.92423,40.66788]}, {"dem":215719,"rep":173665,"total":409109,"name":"Hamilton, Ohio","coordinates":[-84.54418,39.19692]}, {"dem":240403,"rep":148173,"total":406864,"name":"Hartford, Connecticut","coordinates":[-72.73291,41.80605]}, {"dem":345084,"rep":37688,"total":405792,"name":"San Francisco, California","coordinates":[-123.03222,37.72723]}, {"dem":353646,"rep":37797,"total":399522,"name":"Bronx, New York","coordinates":[-73.85293,40.84871]}, {"dem":292561,"rep":67954,"total":399103,"name":"Multnomah, Oregon","coordinates":[-122.41736,45.54771]}, {"dem":218412,"rep":149477,"total":390682,"name":"Baltimore, Maryland","coordinates":[-76.61656,39.44316]}, {"dem":344049,"rep":32811,"total":390385,"name":"Prince George's, Maryland","coordinates":[-76.84818,38.82928]}, {"dem":198778,"rep":157682,"total":383705,"name":"Worcester, Massachusetts","coordinates":[-71.94028,42.31169]}, {"dem":222310,"rep":136316,"total":379868,"name":"Essex, Massachusetts","coordinates":[-70.8649,42.6427]}, {"dem":205609,"rep":159048,"total":379006,"name":"New Haven, Connecticut","coordinates":[-72.9002,41.34971]}, {"dem":212899,"rep":130360,"total":362372,"name":"Marion, Indiana","coordinates":[-86.13579,39.78297]}, {"dem":221819,"rep":119723,"total":361562,"name":"Norfolk, Massachusetts","coordinates":[-71.18111,42.17173]}, {"dem":140624,"rep":201014,"total":361419,"name":"Collin, Texas","coordinates":[-96.57944,33.19453]}, {"dem":190836,"rep":143768,"total":353099,"name":"Jefferson, Kentucky","coordinates":[-85.65762,38.18953]}, {"dem":194402,"rep":132323,"total":351726,"name":"Ventura, California","coordinates":[-119.13314,34.35874]}, {"dem":172538,"rep":146824,"total":348485,"name":"Pierce, Washington","coordinates":[-122.15324,47.05141]}, {"dem":188592,"rep":136582,"total":347790,"name":"Monroe, New York","coordinates":[-77.66465,43.46448]}, {"dem":167060,"rep":164361,"total":344297,"name":"Bucks, Pennsylvania","coordinates":[-75.10706,40.33688]}, {"dem":185227,"rep":128255,"total":342173,"name":"Snohomish, Washington","coordinates":[-121.93678,48.07046]}, {"dem":208992,"rep":116344,"total":337383,"name":"Shelby, Tennessee","coordinates":[-89.89539,35.18379]}, {"dem":244551,"rep":62690,"total":331852,"name":"Denver, Colorado","coordinates":[-104.8811,39.76185]}, {"dem":160121,"rep":152912,"total":330819,"name":"Cobb, Georgia","coordinates":[-84.57411,33.93992]}, {"dem":160776,"rep":138177,"total":328882,"name":"Jefferson, Colorado","coordinates":[-105.24546,39.57951]}, {"dem":166153,"rep":146989,"total":328331,"name":"Gwinnett, Georgia","coordinates":[-84.02308,33.95914]}, {"dem":124908,"rep":191551,"total":326420,"name":"Lee, Florida","coordinates":[-81.89199,26.55903]}, {"dem":193044,"rep":122953,"total":326102,"name":"Middlesex, New Jersey","coordinates":[-74.40743,40.43962]}, {"dem":108010,"rep":179228,"total":318967,"name":"El Paso, Colorado","coordinates":[-104.52747,38.82738]}, {"dem":251370,"rep":51468,"total":314757,"name":"DeKalb, Georgia","coordinates":[-84.22634,33.77066]}, {"dem":119679,"rep":181848,"total":314752,"name":"Brevard, Florida","coordinates":[-80.70033,28.29831]}, {"dem":237882,"rep":57929,"total":314384,"name":"San Mateo, California","coordinates":[-122.37154,37.41467]}, {"dem":137181,"rep":166723,"total":314377,"name":"Monmouth, New Jersey","coordinates":[-74.15244,40.28704]}, {"dem":282830,"rep":12723,"total":311268,"name":"District of Columbia, District of Columbia","coordinates":[-77.01651,38.90424]}, {"dem":240837,"rep":63176,"total":310934,"name":"Essex, New Jersey","coordinates":[-74.24629,40.7874]}, {"dem":217526,"rep":71279,"total":310017,"name":"Dane, Wisconsin","coordinates":[-89.41785,43.06746]}, {"dem":245751,"rep":50421,"total":308741,"name":"Suffolk, Massachusetts","coordinates":[-71.01825,42.33855]}, {"dem":138683,"rep":148180,"total":308184,"name":"Kent, Michigan","coordinates":[-85.54744,43.03249]}, {"dem":156873,"rep":134768,"total":304191,"name":"Jefferson, Alabama","coordinates":[-86.89653,33.55344]}, {"dem":171095,"rep":109767,"total":303520,"name":"Lake, Illinois","coordinates":[-87.43597,42.32644]}, {"dem":159885,"rep":117053,"total":303046,"name":"Arapahoe, Colorado","coordinates":[-104.3317,39.64455]}, {"dem":151927,"rep":132720,"total":300904,"name":"Will, Illinois","coordinates":[-87.97845,41.44847]}, {"dem":110890,"rep":170603,"total":298645,"name":"Denton, Texas","coordinates":[-97.12114,33.20513]}, {"dem":177402,"rep":110667,"total":297634,"name":"Delaware, Pennsylvania","coordinates":[-75.39881,39.91668]}, {"dem":129852,"rep":137490,"total":290090,"name":"Johnson, Kansas","coordinates":[-94.82232,38.8839]}, {"dem":175696,"rep":90326,"total":285790,"name":"Honolulu, Hawaii","coordinates":[-158.1234,21.58002]}, {"dem":117433,"rep":157430,"total":284314,"name":"Polk, Florida","coordinates":[-81.69353,27.95364]}, {"dem":141341,"rep":124049,"total":282319,"name":"Fresno, California","coordinates":[-119.65501,36.761]}, {"dem":143417,"rep":94698,"total":274662,"name":"Bernalillo, New Mexico","coordinates":[-106.66908,35.05362]}, {"dem":87150,"rep":179079,"total":274362,"name":"Ocean, New Jersey","coordinates":[-74.25886,39.86566]}, {"dem":112813,"rep":141569,"total":273942,"name":"Oklahoma, Oklahoma","coordinates":[-97.4094,35.55461]}, {"dem":177738,"rep":70894,"total":273143,"name":"Ramsey, Minnesota","coordinates":[-93.09996,45.0152]}, {"dem":128419,"rep":122403,"total":270081,"name":"Anne Arundel, Maryland","coordinates":[-76.56089,38.99161]}, {"dem":153251,"rep":83197,"total":269232,"name":"Washington, Oregon","coordinates":[-123.09761,45.55354]}, {"dem":141682,"rep":116114,"total":268800,"name":"Chester, Pennsylvania","coordinates":[-75.74975,39.97402]}, {"dem":135513,"rep":115369,"total":266863,"name":"Plymouth, Massachusetts","coordinates":[-70.74194,41.98719]}, {"dem":162919,"rep":85525,"total":262391,"name":"New Castle, Delaware","coordinates":[-75.64413,39.57591]}, {"dem":134686,"rep":117291,"total":262066,"name":"Fort Bend, Texas","coordinates":[-95.77101,29.5266]}, {"dem":109091,"rep":143007,"total":260869,"name":"Volusia, Florida","coordinates":[-81.16179,29.05776]}, {"dem":122016,"rep":123909,"total":258301,"name":"Montgomery, Ohio","coordinates":[-84.29059,39.75373]}, {"dem":134256,"rep":112026,"total":257979,"name":"Summit, Ohio","coordinates":[-81.53492,41.12184]}, {"dem":149248,"rep":98062,"total":257405,"name":"Guilford, North Carolina","coordinates":[-79.78866,36.07906]}, {"dem":115249,"rep":126071,"total":250416,"name":"Morris, New Jersey","coordinates":[-74.54729,40.85889]}, {"dem":148864,"rep":84550,"total":249068,"name":"Davidson, Tennessee","coordinates":[-86.78478,36.16912]}, {"dem":129540,"rep":105443,"total":248959,"name":"Bristol, Massachusetts","coordinates":[-71.08889,41.74858]}, {"dem":142899,"rep":90882,"total":248474,"name":"Providence, Rhode Island","coordinates":[-71.57862,41.86976]}, {"dem":87847,"rep":144258,"total":247054,"name":"Tulsa, Oklahoma","coordinates":[-95.94181,36.12031]}, {"dem":98689,"rep":129584,"total":244163,"name":"Kern, California","coordinates":[-118.7295,35.34662]}, {"dem":90142,"rep":142101,"total":241139,"name":"Pasco, Florida","coordinates":[-82.46483,28.30771]}, {"dem":91093,"rep":137914,"total":241112,"name":"Lancaster, Pennsylvania","coordinates":[-76.25019,40.04199]}, {"dem":113798,"rep":108077,"total":240433,"name":"Douglas, Nebraska","coordinates":[-96.15406,41.29709]}, {"dem":202673,"rep":25205,"total":239402,"name":"Baltimore City, Maryland","coordinates":[-76.61047,39.30003]}, {"dem":79200,"rep":142521,"total":239042,"name":"Waukesha, Wisconsin","coordinates":[-88.30424,43.01836]}, {"dem":119804,"rep":93492,"total":231555,"name":"Polk, Iowa","coordinates":[-93.56897,41.68481]}, {"dem":110483,"rep":99583,"total":231440,"name":"Dakota, Minnesota","coordinates":[-93.06248,44.67089]}, {"dem":160435,"rep":51408,"total":231253,"name":"Sonoma, California","coordinates":[-122.9261,38.52518]}, {"dem":97870,"rep":124438,"total":229063,"name":"Sarasota, Florida","coordinates":[-82.36583,27.18438]}, {"dem":93767,"rep":113435,"total":227246,"name":"Spokane, Washington","coordinates":[-117.40337,47.62037]}, {"dem":146717,"rep":72631,"total":226592,"name":"Camden, New Jersey","coordinates":[-74.96124,39.8024]}, {"dem":105914,"rep":109443,"total":224896,"name":"Seminole, Florida","coordinates":[-81.13198,28.69009]}, {"dem":121124,"rep":88936,"total":224166,"name":"San Joaquin, California","coordinates":[-121.27224,37.93498]}, {"dem":147414,"rep":68114,"total":221975,"name":"Union, New Jersey","coordinates":[-74.30869,40.65987]}, {"dem":163917,"rep":49043,"total":219375,"name":"Hudson, New Jersey","coordinates":[-74.0786,40.73137]}, {"dem":121725,"rep":89272,"total":218943,"name":"Burlington, New Jersey","coordinates":[-74.663,39.87578]}, {"dem":74483,"rep":127832,"total":215165,"name":"Greenville, South Carolina","coordinates":[-82.37207,34.89264]}, {"dem":99589,"rep":100013,"total":214157,"name":"Hillsborough, New Hampshire","coordinates":[-71.72305,42.91153]}, {"dem":102095,"rep":88392,"total":214039,"name":"Clackamas, Oregon","coordinates":[-122.19512,45.16049]}, {"dem":147843,"rep":55512,"total":214008,"name":"El Paso, Texas","coordinates":[-106.24142,31.76648]}, {"dem":97379,"rep":94758,"total":209909,"name":"Washoe, Nevada","coordinates":[-119.66326,40.73131]}, {"dem":112337,"rep":83649,"total":208440,"name":"Onondaga, New York","coordinates":[-76.19613,43.00651]}, {"dem":68524,"rep":128528,"total":205986,"name":"York, Pennsylvania","coordinates":[-76.72888,39.92175]}, {"dem":45835,"rep":150314,"total":204632,"name":"Montgomery, Texas","coordinates":[-95.50295,30.2988]}, {"dem":91032,"rep":98224,"total":203262,"name":"Virginia Beach, Virginia","coordinates":[-76.0252,36.77998]}, {"dem":112590,"rep":78685,"total":203117,"name":"Hampden, Massachusetts","coordinates":[-72.63564,42.13619]}, {"dem":84468,"rep":104175,"total":203081,"name":"Williamson, Texas","coordinates":[-97.60506,30.64908]}, {"dem":28522,"rep":102182,"total":201551,"name":"Utah, Utah","coordinates":[-111.6685,40.12042]}, {"dem":116935,"rep":75625,"total":201205,"name":"Lake, Indiana","coordinates":[-87.37433,41.47224]}, {"dem":68626,"rep":121650,"total":201005,"name":"St. Charles, Missouri","coordinates":[-90.67491,38.7811]}, {"dem":92757,"rep":92441,"total":200160,"name":"Clark, Washington","coordinates":[-122.48595,45.77172]}, {"dem":103665,"rep":82734,"total":199314,"name":"Kane, Illinois","coordinates":[-88.42803,41.93959]}, {"dem":110833,"rep":75698,"total":197556,"name":"Lucas, Ohio","coordinates":[-83.4689,41.68232]}, {"dem":113144,"rep":71721,"total":196538,"name":"Prince William, Virginia","coordinates":[-77.47957,38.70111]}, {"dem":102828,"rep":84660,"total":196491,"name":"East Baton Rouge, Louisiana","coordinates":[-91.09313,30.54392]}, {"dem":102751,"rep":84175,"total":196296,"name":"Genesee, Michigan","coordinates":[-83.70637,43.02107]}, {"dem":93113,"rep":83430,"total":195980,"name":"Larimer, Colorado","coordinates":[-105.48676,40.65809]}, {"dem":75677,"rep":93752,"total":195669,"name":"Ada, Idaho","coordinates":[-116.24437,43.45147]}, {"dem":116759,"rep":72902,"total":194802,"name":"Passaic, New Jersey","coordinates":[-74.29828,41.03788]}, {"dem":96558,"rep":80082,"total":193665,"name":"Adams, Colorado","coordinates":[-104.33187,39.87432]}, {"dem":102753,"rep":67141,"total":191950,"name":"Lane, Oregon","coordinates":[-122.89769,43.92832]}, {"dem":69627,"rep":104353,"total":188783,"name":"Sedgwick, Kansas","coordinates":[-97.46105,37.68104]}, {"dem":128483,"rep":50631,"total":188578,"name":"Washtenaw, Michigan","coordinates":[-83.84342,42.25221]}, {"dem":132334,"rep":41396,"total":188142,"name":"Boulder, Colorado","coordinates":[-105.39769,40.09496]}, {"dem":68657,"rep":102573,"total":187499,"name":"Douglas, Colorado","coordinates":[-104.92598,39.32541]}, {"dem":75500,"rep":93339,"total":185758,"name":"Anoka, Minnesota","coordinates":[-93.24272,45.2741]}, {"dem":100795,"rep":69949,"total":183097,"name":"Loudoun, Virginia","coordinates":[-77.63889,39.0812]}, {"dem":78437,"rep":96626,"total":183065,"name":"Berks, Pennsylvania","coordinates":[-75.92685,40.41395]}, {"dem":73509,"rep":95138,"total":182839,"name":"Placer, California","coordinates":[-120.72271,39.06203]}, {"dem":59669,"rep":116522,"total":182051,"name":"Westmoreland, Pennsylvania","coordinates":[-79.46668,40.31106]}, {"dem":73670,"rep":100398,"total":181639,"name":"Jefferson, Louisiana","coordinates":[-90.081,29.52228]}, {"dem":79994,"rep":90447,"total":181434,"name":"Rockingham, New Hampshire","coordinates":[-71.09908,42.98866]}, {"dem":74143,"rep":101437,"total":180960,"name":"Richmond, New York","coordinates":[-74.13989,40.56126]}, {"dem":62878,"rep":105767,"total":180697,"name":"Knox, Tennessee","coordinates":[-83.93772,35.99272]}, {"dem":71224,"rep":101944,"total":178958,"name":"Manatee, Florida","coordinates":[-82.36876,27.48168]}, {"dem":94464,"rep":75975,"total":178312,"name":"Forsyth, North Carolina","coordinates":[-80.25696,36.13246]}, {"dem":107142,"rep":56365,"total":176786,"name":"Santa Barbara, California","coordinates":[-120.03997,34.53705]}, {"dem":81074,"rep":85045,"total":176461,"name":"Chesterfield, Virginia","coordinates":[-77.58584,37.37843]}, {"dem":89299,"rep":75443,"total":176345,"name":"Charleston, South Carolina","coordinates":[-79.94248,32.80045]}, {"dem":68146,"rep":98388,"total":175239,"name":"Stark, Ohio","coordinates":[-81.36566,40.81413]}, {"dem":62041,"rep":107833,"total":174700,"name":"Marion, Florida","coordinates":[-82.0431,29.2028]}, {"dem":58642,"rep":106976,"total":173839,"name":"Butler, Ohio","coordinates":[-84.56573,39.43974]}, {"dem":118809,"rep":48642,"total":173437,"name":"Hidalgo, Texas","coordinates":[-98.18099,26.39638]}, {"dem":71237,"rep":91557,"total":173275,"name":"Jackson, Missouri","coordinates":[-94.34316,39.00533]}, {"dem":72186,"rep":95116,"total":172737,"name":"Mobile, Alabama","coordinates":[-88.19656,30.68457]}, {"dem":81647,"rep":78494,"total":172146,"name":"Stanislaus, California","coordinates":[-121.00283,37.56231]}, {"dem":102981,"rep":57709,"total":171818,"name":"Cumberland, Maine","coordinates":[-70.33037,43.80834]}, {"dem":61085,"rep":105423,"total":170789,"name":"Collier, Florida","coordinates":[-81.40095,26.11878]}, {"dem":62838,"rep":102188,"total":170462,"name":"Lake, Florida","coordinates":[-81.71228,28.76411]}, {"dem":108000,"rep":52469,"total":168722,"name":"Richland, South Carolina","coordinates":[-80.89803,34.02909]}, {"dem":102360,"rep":51920,"total":166113,"name":"Solano, California","coordinates":[-121.93959,38.26722]}, {"dem":133996,"rep":24292,"total":165812,"name":"Orleans, Louisiana","coordinates":[-89.9345,30.05341]}, {"dem":93935,"rep":59857,"total":163654,"name":"Henrico, Virginia","coordinates":[-77.65192,37.63126]}, {"dem":62822,"rep":89520,"total":163389,"name":"Madison, Alabama","coordinates":[-86.55108,34.76423]}, {"dem":102597,"rep":47484,"total":162193,"name":"Howard, Maryland","coordinates":[-76.9244,39.25226]}, {"dem":81324,"rep":73690,"total":160993,"name":"Lehigh, Pennsylvania","coordinates":[-75.59062,40.61424]}, {"dem":89574,"rep":61257,"total":159776,"name":"Pulaski, Arkansas","coordinates":[-92.31299,34.77031]}, {"dem":85689,"rep":65505,"total":157092,"name":"Somerset, New Jersey","coordinates":[-74.61993,40.56552]}, {"dem":104775,"rep":46193,"total":156529,"name":"Mercer, New Jersey","coordinates":[-74.70372,40.2825]}, {"dem":121250,"rep":28350,"total":156134,"name":"Durham, North Carolina","coordinates":[-78.87812,36.03382]}, {"dem":57263,"rep":87404,"total":154256,"name":"Hamilton, Indiana","coordinates":[-86.02171,40.0535]}, {"dem":57461,"rep":88808,"total":152469,"name":"Escambia, Florida","coordinates":[-87.33889,30.61163]}, {"dem":92068,"rep":53821,"total":152132,"name":"Leon, Florida","coordinates":[-84.2778,30.45931]}, {"dem":68278,"rep":76645,"total":152021,"name":"Orange, New York","coordinates":[-74.30625,41.4024]}, {"dem":55382,"rep":83930,"total":147137,"name":"Allen, Indiana","coordinates":[-85.07179,41.0919]}, {"dem":67086,"rep":64428,"total":144235,"name":"Washington, Minnesota","coordinates":[-92.89011,45.03792]}, {"dem":66272,"rep":71736,"total":143519,"name":"Northampton, Pennsylvania","coordinates":[-75.30744,40.75279]}, {"dem":44973,"rep":88467,"total":142734,"name":"Ottawa, Michigan","coordinates":[-86.65494,42.94246]}, {"dem":55316,"rep":78733,"total":142408,"name":"Hamilton, Tennessee","coordinates":[-85.20184,35.16347]}, {"dem":60803,"rep":71612,"total":141750,"name":"McHenry, Illinois","coordinates":[-88.45224,42.32429]}, {"dem":66881,"rep":70289,"total":140847,"name":"St. Lucie, Florida","coordinates":[-80.44353,27.37981]}, {"dem":66949,"rep":66818,"total":140562,"name":"Lorain, Ohio","coordinates":[-82.17972,41.4388]}, {"dem":85458,"rep":50301,"total":140206,"name":"Osceola, Florida","coordinates":[-81.13931,28.05902]}, {"dem":83077,"rep":47810,"total":139830,"name":"Albany, New York","coordinates":[-73.974,42.58824]}, {"dem":66870,"rep":67544,"total":139542,"name":"Gloucester, New Jersey","coordinates":[-75.14567,39.72287]}, {"dem":108707,"rep":21771,"total":139273,"name":"Marin, California","coordinates":[-122.74597,38.05181]}, {"dem":75452,"rep":55716,"total":138947,"name":"Buncombe, North Carolina","coordinates":[-82.53042,35.60937]}, {"dem":28776,"rep":62219,"total":138411,"name":"Davis, Utah","coordinates":[-112.20194,41.03755]}, {"dem":57788,"rep":63377,"total":136840,"name":"Marion, Oregon","coordinates":[-122.57626,44.90089]}, {"dem":43099,"rep":88684,"total":136514,"name":"St. Johns, Florida","coordinates":[-81.40004,29.89048]}, {"dem":69778,"rep":56894,"total":136315,"name":"Fayette, Kentucky","coordinates":[-84.45827,38.04067]}, {"dem":61898,"rep":61588,"total":136223,"name":"Lancaster, Nebraska","coordinates":[-96.68865,40.78354]}, {"dem":46519,"rep":76651,"total":135428,"name":"Weld, Colorado","coordinates":[-104.38366,40.55596]}, {"dem":69342,"rep":60911,"total":135087,"name":"Rockland, New York","coordinates":[-74.02466,41.15462]}, {"dem":67107,"rep":56164,"total":135009,"name":"San Luis Obispo, California","coordinates":[-120.44754,35.38522]}, {"dem":52451,"rep":78688,"total":134983,"name":"Luzerne, Pennsylvania","coordinates":[-75.97603,41.17278]}, {"dem":72430,"rep":54099,"total":133862,"name":"Barnstable, Massachusetts","coordinates":[-70.21188,41.79901]}, {"dem":47077,"rep":77860,"total":133672,"name":"Harford, Maryland","coordinates":[-76.29978,39.53742]}, {"dem":89088,"rep":34895,"total":133408,"name":"Monterey, California","coordinates":[-121.31557,36.2401]}, {"dem":39410,"rep":89288,"total":132920,"name":"Horry, South Carolina","coordinates":[-78.97667,33.90926]}, {"dem":104235,"rep":20832,"total":131191,"name":"St. Louis City, Missouri","coordinates":[-90.24458,38.63569]}, {"dem":79110,"rep":43868,"total":131138,"name":"Ingham, Michigan","coordinates":[-84.37381,42.60353]}, {"dem":62261,"rep":61797,"total":130934,"name":"Dutchess, New York","coordinates":[-73.74004,41.75476]}, {"dem":64706,"rep":60863,"total":130872,"name":"Dauphin, Pennsylvania","coordinates":[-76.79263,40.41256]}, {"dem":50587,"rep":70490,"total":130179,"name":"Madison, Illinois","coordinates":[-89.90022,38.82711]}, {"dem":47892,"rep":72819,"total":129546,"name":"Pinal, Arizona","coordinates":[-111.36633,32.91852]}, {"dem":68798,"rep":48624,"total":129410,"name":"Thurston, Washington","coordinates":[-122.83015,46.93582]}, {"dem":42728,"rep":78035,"total":129231,"name":"Greene, Missouri","coordinates":[-93.34064,37.25819]}, {"dem":53364,"rep":67199,"total":128979,"name":"Brown, Wisconsin","coordinates":[-87.99613,44.47402]}, {"dem":95249,"rep":22438,"total":128821,"name":"Santa Cruz, California","coordinates":[-122.0072,37.01248]}, {"dem":75820,"rep":46834,"total":128571,"name":"Alachua, Florida","coordinates":[-82.35722,29.67574]}, {"dem":71605,"rep":51265,"total":127506,"name":"Cumberland, North Carolina","coordinates":[-78.82871,35.05019]}, {"dem":67148,"rep":51034,"total":126299,"name":"Kalamazoo, Michigan","coordinates":[-85.53285,42.24626]}, {"dem":56522,"rep":59522,"total":125677,"name":"Frederick, Maryland","coordinates":[-77.39762,39.47021]}, {"dem":27717,"rep":90915,"total":124392,"name":"St. Tammany, Louisiana","coordinates":[-89.95196,30.41002]}, {"dem":63156,"rep":49018,"total":124317,"name":"Kitsap, Washington","coordinates":[-122.64963,47.63959]}, {"dem":58112,"rep":60069,"total":123679,"name":"Erie, Pennsylvania","coordinates":[-80.09638,42.11795]}, {"dem":62278,"rep":54058,"total":123528,"name":"New London, Connecticut","coordinates":[-72.10863,41.47265]}, {"dem":43658,"rep":73757,"total":122903,"name":"Galveston, Texas","coordinates":[-94.88845,29.23345]}, {"dem":35230,"rep":80026,"total":122093,"name":"Lexington, South Carolina","coordinates":[-81.26627,33.89947]}, {"dem":47085,"rep":69076,"total":121617,"name":"Cumberland, Pennsylvania","coordinates":[-77.26344,40.1648]}, {"dem":92016,"rep":20186,"total":121356,"name":"Arlington, Virginia","coordinates":[-77.1007,38.87833]}, {"dem":43200,"rep":72791,"total":121181,"name":"Brazoria, Texas","coordinates":[-95.43464,29.16781]}, {"dem":39997,"rep":76277,"total":121090,"name":"Spartanburg, South Carolina","coordinates":[-81.99105,34.93327]}, {"dem":60756,"rep":53857,"total":120580,"name":"St. Clair, Illinois","coordinates":[-89.92854,38.47019]}, {"dem":55713,"rep":55624,"total":118376,"name":"Winnebago, Illinois","coordinates":[-89.1612,42.33739]}, {"dem":60924,"rep":52690,"total":117291,"name":"Atlantic, New Jersey","coordinates":[-74.63375,39.46935]}, {"dem":33730,"rep":77643,"total":117267,"name":"Warren, Ohio","coordinates":[-84.1699,39.42565]}, {"dem":58935,"rep":48390,"total":117098,"name":"Linn, Iowa","coordinates":[-91.59767,42.07795]}, {"dem":46397,"rep":64255,"total":116246,"name":"Lake, Ohio","coordinates":[-81.39264,41.92411]}, {"dem":57381,"rep":53616,"total":115072,"name":"Mahoning, Ohio","coordinates":[-80.77039,41.01087]}, {"dem":35590,"rep":71330,"total":114450,"name":"Yavapai, Arizona","coordinates":[-112.57722,34.63107]}, {"dem":41593,"rep":66754,"total":114357,"name":"York, South Carolina","coordinates":[-81.18318,34.97018]}, {"dem":55844,"rep":50403,"total":114274,"name":"York, Maine","coordinates":[-70.66842,43.42601]}, {"dem":50913,"rep":54575,"total":114094,"name":"Saratoga, New York","coordinates":[-73.85538,43.10613]}, {"dem":52627,"rep":54047,"total":112705,"name":"Chesapeake, Virginia","coordinates":[-76.30178,36.67937]}, {"dem":57771,"rep":44630,"total":112422,"name":"Saint Louis, Minnesota","coordinates":[-92.51456,47.57863]}, {"dem":47585,"rep":58299,"total":112334,"name":"Tulare, California","coordinates":[-118.78105,36.22883]}, {"dem":62290,"rep":45688,"total":112142,"name":"Chatham, Georgia","coordinates":[-81.08518,31.9804]}, {"dem":25231,"rep":80649,"total":112043,"name":"Cherokee, Georgia","coordinates":[-84.47505,34.24431]}, {"dem":50979,"rep":55344,"total":111905,"name":"New Hanover, North Carolina","coordinates":[-77.8642,34.18344]}, {"dem":45304,"rep":57476,"total":110176,"name":"Clay, Missouri","coordinates":[-94.4215,39.31555]}, {"dem":52252,"rep":52021,"total":110060,"name":"St. Joseph, Indiana","coordinates":[-86.28804,41.61772]}, {"dem":60340,"rep":40599,"total":109673,"name":"Whatcom, Washington","coordinates":[-121.83643,48.84265]}, {"dem":38829,"rep":62538,"total":109450,"name":"Cleveland, Oklahoma","coordinates":[-97.32308,35.20637]}, {"dem":44447,"rep":53870,"total":109327,"name":"Jackson, Oregon","coordinates":[-122.67561,42.41162]}, {"dem":36706,"rep":64515,"total":107436,"name":"Rutherford, Tennessee","coordinates":[-86.41721,35.84336]}, {"dem":27822,"rep":74963,"total":106483,"name":"Clay, Florida","coordinates":[-81.86503,29.98658]}, {"dem":31013,"rep":68212,"total":106271,"name":"Williamson, Tennessee","coordinates":[-86.89806,35.8948]}, {"dem":31568,"rep":69036,"total":106238,"name":"Jefferson, Missouri","coordinates":[-90.54368,38.25762]}, {"dem":39333,"rep":62611,"total":106008,"name":"Sussex, Delaware","coordinates":[-75.33702,38.67322]}, {"dem":34384,"rep":65680,"total":105866,"name":"Livingston, Michigan","coordinates":[-83.91171,42.60253]}, {"dem":53483,"rep":49006,"total":105804,"name":"Caddo, Louisiana","coordinates":[-93.88242,32.57719]}, {"dem":34337,"rep":66707,"total":105710,"name":"Union, North Carolina","coordinates":[-80.53042,34.99182]}, {"dem":32726,"rep":68195,"total":105603,"name":"Lafayette, Louisiana","coordinates":[-92.06416,30.2065]}, {"dem":49198,"rep":50766,"total":104405,"name":"Nueces, Texas","coordinates":[-97.51621,27.74003]}, {"dem":40872,"rep":57568,"total":103860,"name":"Delaware, Ohio","coordinates":[-83.00746,40.27894]}, {"dem":81259,"rep":15581,"total":103484,"name":"Richmond, Virginia","coordinates":[-77.476,37.53139]}, {"dem":51983,"rep":48384,"total":103456,"name":"Lackawanna, Pennsylvania","coordinates":[-75.60966,41.44028]}, {"dem":36322,"rep":61386,"total":101450,"name":"Washington, Pennsylvania","coordinates":[-80.25213,40.2]}, {"dem":22977,"rep":73020,"total":101254,"name":"Shelby, Alabama","coordinates":[-86.67808,33.26304]}, {"dem":23780,"rep":71893,"total":100855,"name":"Okaloosa, Florida","coordinates":[-86.59418,30.66585]}, {"dem":26715,"rep":67518,"total":99121,"name":"Clermont, Ohio","coordinates":[-84.14948,39.05205]}, {"dem":28023,"rep":65651,"total":99013,"name":"Lubbock, Texas","coordinates":[-101.81994,33.61146]}, {"dem":50057,"rep":45724,"total":98766,"name":"Henry, Georgia","coordinates":[-84.15402,33.45294]}, {"dem":42444,"rep":45692,"total":98557,"name":"Deschutes, Oregon","coordinates":[-121.22557,43.91511]}, {"dem":40907,"rep":49944,"total":98373,"name":"Sangamon, Illinois","coordinates":[-89.66242,39.75686]}, {"dem":23462,"rep":69851,"total":98221,"name":"Forsyth, Georgia","coordinates":[-84.1274,34.22514]}, {"dem":39775,"rep":53051,"total":97442,"name":"Litchfield, Connecticut","coordinates":[-73.2354,41.79188]}, {"dem":28584,"rep":64428,"total":97071,"name":"Butler, Pennsylvania","coordinates":[-79.91897,40.91384]}, {"dem":28005,"rep":60871,"total":96824,"name":"Benton, Arkansas","coordinates":[-94.25629,36.33781]}, {"dem":31177,"rep":61798,"total":96431,"name":"Gaston, North Carolina","coordinates":[-81.17725,35.29334]}, {"dem":33445,"rep":60218,"total":96374,"name":"Charlotte, Florida","coordinates":[-81.94127,26.86897]}, {"dem":43014,"rep":49024,"total":96029,"name":"Trumbull, Ohio","coordinates":[-80.77039,41.30637]}, {"dem":58916,"rep":34003,"total":95878,"name":"Montgomery, Alabama","coordinates":[-86.20446,32.20288]}, {"dem":41567,"rep":45144,"total":95564,"name":"Butte, California","coordinates":[-121.60191,39.66595]}, {"dem":18458,"rep":72883,"total":95215,"name":"Baldwin, Alabama","coordinates":[-87.74606,30.65921]}, {"dem":37801,"rep":51998,"total":94994,"name":"Bell, Texas","coordinates":[-97.48126,31.04274]}, {"dem":67594,"rep":25275,"total":94681,"name":"Hinds, Mississippi","coordinates":[-90.46601,32.26778]}, {"dem":44396,"rep":45469,"total":94320,"name":"Saginaw, Michigan","coordinates":[-84.05541,43.32826]}, {"dem":42512,"rep":46611,"total":94133,"name":"Racine, Wisconsin","coordinates":[-87.42087,42.75412]}, {"dem":38087,"rep":49884,"total":93868,"name":"Outagamie, Wisconsin","coordinates":[-88.46498,44.41822]}, {"dem":31795,"rep":58970,"total":93796,"name":"Hernando, Florida","coordinates":[-82.46622,28.57304]}, {"dem":36404,"rep":49247,"total":93591,"name":"El Dorado, California","coordinates":[-120.53422,38.78561]}, {"dem":35521,"rep":53819,"total":93289,"name":"Cabarrus, North Carolina","coordinates":[-80.55272,35.38834]}, {"dem":78220,"rep":12645,"total":92859,"name":"Clayton, Georgia","coordinates":[-84.35557,33.54268]}, {"dem":35559,"rep":51961,"total":92402,"name":"Niagara, New York","coordinates":[-78.79214,43.45673]}, {"dem":59402,"rep":29472,"total":92079,"name":"Cameron, Texas","coordinates":[-97.47895,26.10292]}, {"dem":26567,"rep":58215,"total":91848,"name":"Carroll, Maryland","coordinates":[-77.01532,39.56333]}, {"dem":50137,"rep":33368,"total":91628,"name":"Champaign, Illinois","coordinates":[-88.19697,40.13898]}, {"dem":32182,"rep":54810,"total":91373,"name":"Medina, Ohio","coordinates":[-81.89976,41.11617]}, {"dem":33743,"rep":51437,"total":91009,"name":"Oneida, New York","coordinates":[-75.43428,43.24272]}, {"dem":45357,"rep":38867,"total":88624,"name":"Middlesex, Connecticut","coordinates":[-72.52278,41.433]}, {"dem":18464,"rep":65339,"total":87745,"name":"Santa Rosa, Florida","coordinates":[-87.01289,30.70126]}, {"dem":42443,"rep":42862,"total":87618,"name":"Jefferson, Texas","coordinates":[-94.14933,29.85399]}, {"dem":21797,"rep":62194,"total":87453,"name":"Bay, Florida","coordinates":[-85.63167,30.23821]}, {"dem":37054,"rep":43448,"total":87144,"name":"Winnebago, Wisconsin","coordinates":[-88.66814,44.0857]}, {"dem":40440,"rep":39149,"total":86220,"name":"Scott, Iowa","coordinates":[-90.62228,41.64207]}, {"dem":39212,"rep":40943,"total":86072,"name":"Broome, New York","coordinates":[-75.83028,42.16197]}, {"dem":28362,"rep":54372,"total":85909,"name":"Johnston, North Carolina","coordinates":[-78.36734,35.51341]}, {"dem":30185,"rep":53204,"total":85792,"name":"Martin, Florida","coordinates":[-80.3982,27.0836]}, {"dem":23131,"rep":40235,"total":85039,"name":"Weber, Utah","coordinates":[-111.87688,41.27032]}, {"dem":22300,"rep":58930,"total":84768,"name":"Smith, Texas","coordinates":[-95.27004,32.37701]}, {"dem":41125,"rep":36200,"total":83868,"name":"Boone, Missouri","coordinates":[-92.3102,38.98986]}, {"dem":26296,"rep":54191,"total":83785,"name":"Calcasieu, Louisiana","coordinates":[-93.35801,30.22955]}, {"dem":40198,"rep":37674,"total":83648,"name":"Merrimack, New Hampshire","coordinates":[-71.68004,43.29957]}, {"dem":32531,"rep":48167,"total":83571,"name":"Beaver, Pennsylvania","coordinates":[-80.35072,40.68414]}, {"dem":54814,"rep":18601,"total":83418,"name":"Chittenden, Vermont","coordinates":[-73.0694,44.46332]}, {"dem":57023,"rep":21552,"total":83388,"name":"Norfolk, Virginia","coordinates":[-76.24464,36.92301]}, {"dem":55367,"rep":21790,"total":82956,"name":"Hampshire, Massachusetts","coordinates":[-72.66369,42.33945]}, {"dem":27376,"rep":51241,"total":82761,"name":"Licking, Ohio","coordinates":[-82.48343,40.0915]}, {"dem":31762,"rep":47723,"total":82700,"name":"Tuscaloosa, Alabama","coordinates":[-87.52278,33.29021]}, {"dem":24734,"rep":54754,"total":82567,"name":"Iredell, North Carolina","coordinates":[-80.87452,35.80624]}, {"dem":59923,"rep":18557,"total":82340,"name":"Orange, North Carolina","coordinates":[-79.12003,36.06252]}, {"dem":54752,"rep":20739,"total":82090,"name":"Yolo, California","coordinates":[-121.90244,38.67959]}, {"dem":37788,"rep":38336,"total":82053,"name":"Kent, Rhode Island","coordinates":[-71.58092,41.67424]}, {"dem":33366,"rep":41476,"total":81861,"name":"Washington, Arkansas","coordinates":[-94.21726,35.978]}, {"dem":28943,"rep":48540,"total":81858,"name":"Greene, Ohio","coordinates":[-83.89489,39.68747]}, {"dem":42101,"rep":34006,"total":81355,"name":"Ulster, New York","coordinates":[-74.26545,41.94721]}, {"dem":31361,"rep":39816,"total":80821,"name":"Cass, North Dakota","coordinates":[-97.25237,46.927]}, {"dem":28033,"rep":45143,"total":80580,"name":"Sarpy, Nebraska","coordinates":[-96.10912,41.11506]}, {"dem":32838,"rep":41622,"total":80540,"name":"Penobscot, Maine","coordinates":[-68.66661,45.40928]}, {"dem":41824,"rep":35691,"total":80527,"name":"Pitt, North Carolina","coordinates":[-77.37273,35.59248]}, {"dem":21097,"rep":56232,"total":80483,"name":"Anderson, South Carolina","coordinates":[-82.6386,34.52123]}, {"dem":36268,"rep":35668,"total":80129,"name":"Olmsted, Minnesota","coordinates":[-92.41009,43.99949]}, {"dem":22301,"rep":51778,"total":80053,"name":"Shasta, California","coordinates":[-122.04355,40.76051]}, {"dem":26360,"rep":47194,"total":80027,"name":"Benton, Washington","coordinates":[-119.51665,46.22812]}, {"dem":29043,"rep":48620,"total":80009,"name":"Indian River, Florida","coordinates":[-80.57478,27.70052]}, {"dem":17455,"rep":58282,"total":79943,"name":"Mohave, Arizona","coordinates":[-113.74968,35.7177]}, {"dem":36196,"rep":37237,"total":79835,"name":"McLean, Illinois","coordinates":[-88.84453,40.49455]}, {"dem":22789,"rep":54456,"total":79700,"name":"Citrus, Florida","coordinates":[-82.5248,28.84364]}, {"dem":25576,"rep":47617,"total":79592,"name":"Stearns, Minnesota","coordinates":[-94.61048,45.55523]}, {"dem":30705,"rep":44587,"total":79517,"name":"Berkeley, South Carolina","coordinates":[-79.95365,33.2077]}, {"dem":27063,"rep":48260,"total":79075,"name":"McLennan, Texas","coordinates":[-97.20151,31.54959]}, {"dem":35875,"rep":36265,"total":78646,"name":"Pueblo, Colorado","coordinates":[-104.48989,38.17065]}, {"dem":32138,"rep":42922,"total":78524,"name":"Beaufort, South Carolina","coordinates":[-80.68942,32.35811]}, {"dem":38060,"rep":35633,"total":78503,"name":"Peoria, Illinois","coordinates":[-89.76699,40.78597]}, {"dem":49341,"rep":25614,"total":78303,"name":"Charles, Maryland","coordinates":[-77.01542,38.47285]}, {"dem":30610,"rep":42043,"total":78263,"name":"Minnehaha, South Dakota","coordinates":[-96.79572,43.66747]}, {"dem":37304,"rep":36127,"total":78088,"name":"Muskegon, Michigan","coordinates":[-86.75189,43.28925]}, {"dem":24553,"rep":49051,"total":78003,"name":"St. Clair, Michigan","coordinates":[-82.66891,42.9288]}, {"dem":20855,"rep":51729,"total":78003,"name":"Washington, Wisconsin","coordinates":[-88.23291,43.39115]}, {"dem":31291,"rep":41735,"total":77750,"name":"Yakima, Washington","coordinates":[-120.74014,46.45655]}, {"dem":21729,"rep":49779,"total":77653,"name":"Mesa, Colorado","coordinates":[-108.46057,39.01952]}, {"dem":38506,"rep":34194,"total":77424,"name":"Tolland, Connecticut","coordinates":[-72.34097,41.85808]}, {"dem":33676,"rep":38832,"total":77190,"name":"Porter, Indiana","coordinates":[-87.07131,41.50991]}, {"dem":35771,"rep":36025,"total":77076,"name":"Kenosha, Wisconsin","coordinates":[-87.425,42.5797]}, {"dem":50200,"rep":21044,"total":76940,"name":"Johnson, Iowa","coordinates":[-91.59052,41.67066]}, {"dem":22638,"rep":52730,"total":76665,"name":"Sumter, Florida","coordinates":[-82.07434,28.7141]}, {"dem":37088,"rep":35274,"total":76148,"name":"Centre, Pennsylvania","coordinates":[-77.84787,40.90912]}, {"dem":32397,"rep":39971,"total":76139,"name":"Portage, Ohio","coordinates":[-81.19696,41.16897]}, {"dem":39343,"rep":31488,"total":76068,"name":"Rock, Wisconsin","coordinates":[-89.07528,42.66988]}, {"dem":57242,"rep":13285,"total":75770,"name":"Alexandria, Virginia","coordinates":[-77.08366,38.81925]}, {"dem":45618,"rep":25468,"total":75715,"name":"Newport News, Virginia","coordinates":[-76.52198,37.07613]}, {"dem":28263,"rep":43850,"total":75690,"name":"Kanawha, West Virginia","coordinates":[-81.52351,38.32806]}, {"dem":22600,"rep":48337,"total":75559,"name":"Hendricks, Indiana","coordinates":[-86.5099,39.76896]}, {"dem":48814,"rep":24461,"total":75515,"name":"Richmond, Georgia","coordinates":[-82.07499,33.36148]}, {"dem":33926,"rep":35934,"total":75406,"name":"Shawnee, Kansas","coordinates":[-95.75566,39.0418]}, {"dem":28502,"rep":39948,"total":75029,"name":"Scott, Minnesota","coordinates":[-93.53373,44.6518]}, {"dem":18109,"rep":54317,"total":74856,"name":"Davidson, North Carolina","coordinates":[-80.2071,35.79513]}, {"dem":25455,"rep":46025,"total":74851,"name":"Aiken, South Carolina","coordinates":[-81.63298,33.55001]}, {"dem":33351,"rep":36991,"total":74598,"name":"Kent, Delaware","coordinates":[-75.50298,39.09708]}, {"dem":26863,"rep":43261,"total":74218,"name":"Monroe, Michigan","coordinates":[-83.4871,41.91609]}, {"dem":24212,"rep":46658,"total":74126,"name":"Sussex, New Jersey","coordinates":[-74.69191,41.13746]}, {"dem":24881,"rep":44314,"total":72913,"name":"Fairfield, Ohio","coordinates":[-82.62668,39.74769]}, {"dem":16883,"rep":47222,"total":72785,"name":"Canyon, Idaho","coordinates":[-116.70905,43.62579]}, {"dem":28530,"rep":40496,"total":72507,"name":"Vanderburgh, Indiana","coordinates":[-87.58616,38.02007]}, {"dem":21216,"rep":48324,"total":72351,"name":"Catawba, North Carolina","coordinates":[-81.2149,35.66188]}, {"dem":33224,"rep":33826,"total":72164,"name":"Hays, Texas","coordinates":[-98.02926,30.06122]}, {"dem":29495,"rep":38647,"total":72031,"name":"Berrien, Michigan","coordinates":[-86.74254,41.79138]}, {"dem":24214,"rep":42958,"total":71998,"name":"Kenton, Kentucky","coordinates":[-84.53343,38.9305]}, {"dem":32717,"rep":33726,"total":71562,"name":"Rensselaer, New York","coordinates":[-73.51384,42.71042]}, {"dem":18161,"rep":50129,"total":71505,"name":"Sumner, Tennessee","coordinates":[-86.45979,36.47344]}, {"dem":50793,"rep":14332,"total":71434,"name":"Santa Fe, New Mexico","coordinates":[-105.96397,35.51453]}, {"dem":29833,"rep":38815,"total":71157,"name":"Alamance, North Carolina","coordinates":[-79.40057,36.04395]}, {"dem":28898,"rep":38712,"total":70836,"name":"Hunterdon, New Jersey","coordinates":[-74.91196,40.56528]}, {"dem":37317,"rep":28725,"total":70789,"name":"Merced, California","coordinates":[-120.7228,37.1948]}, {"dem":16180,"rep":51733,"total":70694,"name":"Hall, Georgia","coordinates":[-83.81849,34.31756]}, {"dem":37947,"rep":25374,"total":70648,"name":"Dona Ana, New Mexico","coordinates":[-106.83496,32.34991]}, {"dem":33918,"rep":33386,"total":69752,"name":"Monroe, Pennsylvania","coordinates":[-75.32906,41.05624]}, {"dem":17465,"rep":49768,"total":69731,"name":"Franklin, Pennsylvania","coordinates":[-77.72452,39.92677]}, {"dem":25795,"rep":39793,"total":69677,"name":"Jackson, Michigan","coordinates":[-84.42086,42.24847]}, {"dem":20334,"rep":43274,"total":69618,"name":"Wright, Minnesota","coordinates":[-93.96639,45.17509]}, {"dem":26477,"rep":39013,"total":69515,"name":"Marathon, Wisconsin","coordinates":[-89.75782,44.89803]}, {"dem":22171,"rep":40920,"total":69108,"name":"Yellowstone, Montana","coordinates":[-108.27665,45.93698]}, {"dem":39851,"rep":26976,"total":69032,"name":"Muscogee, Georgia","coordinates":[-84.87494,32.51019]}, {"dem":34894,"rep":29072,"total":69000,"name":"Strafford, New Hampshire","coordinates":[-71.03558,43.29327]}, {"dem":23282,"rep":42720,"total":68351,"name":"Brunswick, North Carolina","coordinates":[-78.22776,34.03875]}, {"dem":24428,"rep":41734,"total":68017,"name":"Ouachita, Louisiana","coordinates":[-92.15158,32.48093]}, {"dem":33747,"rep":28953,"total":67280,"name":"Schenectady, New York","coordinates":[-74.04355,42.81755]}, {"dem":23121,"rep":38738,"total":67211,"name":"Brazos, Texas","coordinates":[-96.30239,30.65671]}, {"dem":17318,"rep":45456,"total":66500,"name":"Johnson, Indiana","coordinates":[-86.09426,39.49609]}, {"dem":33741,"rep":27230,"total":66369,"name":"Washington, Rhode Island","coordinates":[-71.62028,41.39679]}, {"dem":16264,"rep":44449,"total":66310,"name":"Kootenai, Idaho","coordinates":[-116.69592,47.67596]}, {"dem":29302,"rep":31675,"total":66208,"name":"Kennebec, Maine","coordinates":[-69.76576,44.41701]}, {"dem":21129,"rep":40998,"total":65991,"name":"Washington, Maryland","coordinates":[-77.81467,39.60362]}, {"dem":27908,"rep":33868,"total":65934,"name":"Stafford, Virginia","coordinates":[-77.45133,38.41326]}, {"dem":20591,"rep":43089,"total":65695,"name":"DeSoto, Mississippi","coordinates":[-89.99324,34.87426]}, {"dem":20740,"rep":41867,"total":65630,"name":"Elkhart, Indiana","coordinates":[-85.86398,41.60069]}, {"dem":18025,"rep":44662,"total":64890,"name":"Paulding, Georgia","coordinates":[-84.86716,33.92102]}, {"dem":41259,"rep":17501,"total":64867,"name":"Hawaii, Hawaii","coordinates":[-155.50244,19.59776]}, {"dem":43714,"rep":16839,"total":64803,"name":"Berkshire, Massachusetts","coordinates":[-73.21792,42.37149]}, {"dem":18887,"rep":43085,"total":64743,"name":"Columbia, Georgia","coordinates":[-82.25229,33.54763]}, {"dem":13194,"rep":49430,"total":64575,"name":"Randolph, North Carolina","coordinates":[-79.80621,35.70991]}, {"dem":32233,"rep":27476,"total":64405,"name":"Black Hawk, Iowa","coordinates":[-92.3076,42.47113]}, {"dem":20685,"rep":38707,"total":64400,"name":"Tazewell, Illinois","coordinates":[-89.51625,40.50807]}, {"dem":19400,"rep":42810,"total":64369,"name":"Rowan, North Carolina","coordinates":[-80.52172,35.64135]}, {"dem":27318,"rep":32498,"total":64341,"name":"Wood, Ohio","coordinates":[-83.62268,41.36018]}, {"dem":32298,"rep":26998,"total":63994,"name":"Rock Island, Illinois","coordinates":[-90.57212,41.46842]}, {"dem":16253,"rep":44941,"total":63673,"name":"Ellis, Texas","coordinates":[-96.79694,32.34687]}, {"dem":21169,"rep":40354,"total":63313,"name":"Harrison, Mississippi","coordinates":[-89.08337,30.41653]}, {"dem":18867,"rep":42258,"total":63072,"name":"Cambria, Pennsylvania","coordinates":[-78.71047,40.51022]}, {"dem":32406,"rep":26389,"total":62968,"name":"La Crosse, Wisconsin","coordinates":[-91.11175,43.90822]}, {"dem":16770,"rep":44001,"total":62869,"name":"Schuylkill, Pennsylvania","coordinates":[-76.21778,40.70368]}, {"dem":14110,"rep":47178,"total":62768,"name":"Rankin, Mississippi","coordinates":[-89.94606,32.26712]}, {"dem":19382,"rep":39630,"total":62753,"name":"Hanover, Virginia","coordinates":[-77.49131,37.76021]}, {"dem":36787,"rep":24043,"total":62596,"name":"Bibb, Georgia","coordinates":[-83.69419,32.80884]}, {"dem":24055,"rep":34987,"total":62567,"name":"Dorchester, South Carolina","coordinates":[-80.40469,33.08218]}, {"dem":24207,"rep":34623,"total":62562,"name":"Spotsylvania, Virginia","coordinates":[-77.65722,38.18243]}, {"dem":27282,"rep":30768,"total":62515,"name":"Tippecanoe, Indiana","coordinates":[-86.89355,40.38913]}, {"dem":41312,"rep":17902,"total":62356,"name":"Hampton, Virginia","coordinates":[-76.29729,37.04796]}, {"dem":12578,"rep":46979,"total":62278,"name":"Sullivan, Tennessee","coordinates":[-82.30133,36.50968]}, {"dem":14238,"rep":45136,"total":62178,"name":"Comal, Texas","coordinates":[-98.26054,29.80549]}, {"dem":10288,"rep":42650,"total":61963,"name":"Washington, Utah","coordinates":[-113.4878,37.26253]}, {"dem":18953,"rep":40525,"total":61845,"name":"Lebanon, Pennsylvania","coordinates":[-76.46481,40.37144]}, {"dem":16583,"rep":42533,"total":61745,"name":"Coweta, Georgia","coordinates":[-84.76213,33.35289]}, {"dem":27707,"rep":25905,"total":61690,"name":"Sandoval, New Mexico","coordinates":[-106.88311,35.68509]}, {"dem":23328,"rep":35205,"total":61429,"name":"Clark, Ohio","coordinates":[-83.78367,39.91703]}, {"dem":39199,"rep":17411,"total":61372,"name":"Napa, California","coordinates":[-122.3259,38.50709]}, {"dem":23284,"rep":35048,"total":60913,"name":"Fayette, Georgia","coordinates":[-84.49394,33.41271]}, {"dem":22553,"rep":35430,"total":60079,"name":"Houston, Georgia","coordinates":[-83.66252,32.45828]}, {"dem":32404,"rep":21108,"total":59784,"name":"Coconino, Arizona","coordinates":[-111.77372,35.82969]}, {"dem":22956,"rep":32458,"total":59655,"name":"Sheboygan, Wisconsin","coordinates":[-87.73151,43.74123]}, {"dem":33200,"rep":18373,"total":59246,"name":"Humboldt, California","coordinates":[-123.92617,40.70665]}, {"dem":31543,"rep":22250,"total":59203,"name":"Missoula, Montana","coordinates":[-113.89269,47.02726]}, {"dem":21230,"rep":34617,"total":59191,"name":"Lee, Alabama","coordinates":[-85.35304,32.60406]}, {"dem":24157,"rep":31494,"total":58902,"name":"Calhoun, Michigan","coordinates":[-85.01238,42.24298]}, {"dem":17995,"rep":33488,"total":58719,"name":"Linn, Oregon","coordinates":[-122.5372,44.48889]}, {"dem":34216,"rep":20592,"total":58454,"name":"Monroe, Indiana","coordinates":[-86.52331,39.16072]}, {"dem":19827,"rep":35809,"total":58176,"name":"Henderson, North Carolina","coordinates":[-82.47974,35.33641]}, {"dem":26710,"rep":29573,"total":57931,"name":"Florence, South Carolina","coordinates":[-79.71023,34.02853]}, {"dem":18391,"rep":36632,"total":57822,"name":"Guadalupe, Texas","coordinates":[-97.94677,29.58353]}, {"dem":31005,"rep":24817,"total":57738,"name":"Douglas, Georgia","coordinates":[-84.76731,33.70124]}, {"dem":6950,"rep":48824,"total":57730,"name":"Livingston, Louisiana","coordinates":[-90.72747,30.44041]}, {"dem":21699,"rep":32341,"total":57620,"name":"Montgomery, Tennessee","coordinates":[-87.38088,36.50035]}, {"dem":15026,"rep":39082,"total":57618,"name":"Boone, Kentucky","coordinates":[-84.73637,38.9589]}, {"dem":10988,"rep":44382,"total":57606,"name":"Johnson, Texas","coordinates":[-97.36495,32.37982]}, {"dem":22026,"rep":33850,"total":57503,"name":"Flagler, Florida","coordinates":[-81.28625,29.47489]}, {"dem":17514,"rep":37122,"total":57135,"name":"Onslow, North Carolina","coordinates":[-77.49946,34.7631]}, {"dem":42307,"rep":12947,"total":56905,"name":"Webb, Texas","coordinates":[-99.34075,27.76079]}, {"dem":18322,"rep":36816,"total":56844,"name":"Rapides, Louisiana","coordinates":[-92.53595,31.1932]}, {"dem":8344,"rep":46473,"total":56817,"name":"Parker, Texas","coordinates":[-97.8059,32.77709]}, {"dem":14385,"rep":39406,"total":56734,"name":"Wilson, Tennessee","coordinates":[-86.29124,36.14952]}, {"dem":33345,"rep":19259,"total":56726,"name":"Albemarle, Virginia","coordinates":[-78.5535,38.02418]}, {"dem":24938,"rep":27609,"total":56221,"name":"Eaton, Michigan","coordinates":[-84.84644,42.58953]}, {"dem":26690,"rep":24736,"total":55968,"name":"Skagit, Washington","coordinates":[-121.81577,48.49329]}, {"dem":18050,"rep":34183,"total":55786,"name":"Allegan, Michigan","coordinates":[-86.63474,42.59578]}, {"dem":21508,"rep":29056,"total":55696,"name":"Carver, Minnesota","coordinates":[-93.80009,44.82131]}, {"dem":23009,"rep":28227,"total":55601,"name":"Androscoggin, Maine","coordinates":[-70.20743,44.16768]}, {"dem":11674,"rep":39986,"total":55278,"name":"Canadian, Oklahoma","coordinates":[-97.97988,35.54335]}, {"dem":16085,"rep":36590,"total":55214,"name":"Richland, Ohio","coordinates":[-82.54278,40.77415]}, {"dem":26053,"rep":23365,"total":54935,"name":"Nevada, California","coordinates":[-120.77134,39.2975]}, {"dem":13958,"rep":39135,"total":54909,"name":"Blair, Pennsylvania","coordinates":[-78.30959,40.49865]}, {"dem":27294,"rep":23311,"total":54885,"name":"Eau Claire, Wisconsin","coordinates":[-91.28641,44.72635]}, {"dem":16476,"rep":36143,"total":54678,"name":"Ascension, Louisiana","coordinates":[-90.9125,30.20644]}, {"dem":20168,"rep":30430,"total":54523,"name":"Ozaukee, Wisconsin","coordinates":[-87.4993,43.36075]}, {"dem":8367,"rep":43462,"total":54305,"name":"Randall, Texas","coordinates":[-101.89554,34.96252]}, {"dem":19091,"rep":31594,"total":54234,"name":"Chautauqua, New York","coordinates":[-79.40759,42.30421]}, {"dem":27771,"rep":24453,"total":54004,"name":"Cumberland, New Jersey","coordinates":[-75.12162,39.32843]}, {"dem":18595,"rep":32376,"total":53909,"name":"Madison, Indiana","coordinates":[-85.72245,40.1662]}, {"dem":24246,"rep":23802,"total":53819,"name":"Gallatin, Montana","coordinates":[-111.16392,45.51805]}, {"dem":17946,"rep":34590,"total":53767,"name":"Fayette, Pennsylvania","coordinates":[-79.64011,39.9189]}, {"dem":14096,"rep":34582,"total":53521,"name":"Douglas, Oregon","coordinates":[-123.15447,43.28632]}, {"dem":24884,"rep":24961,"total":53447,"name":"Kendall, Illinois","coordinates":[-88.43062,41.58814]}, {"dem":24605,"rep":25165,"total":53010,"name":"Yuma, Arizona","coordinates":[-113.9109,32.77394]}, {"dem":21642,"rep":28328,"total":52977,"name":"Bay, Michigan","coordinates":[-83.9787,43.69971]}, {"dem":13120,"rep":37079,"total":52734,"name":"Miami, Ohio","coordinates":[-84.22841,40.05332]}, {"dem":16878,"rep":33959,"total":52416,"name":"Tangipahoa, Louisiana","coordinates":[-90.40663,30.62153]}, {"dem":18733,"rep":31544,"total":52309,"name":"Mercer, Pennsylvania","coordinates":[-80.25278,41.30001]}, {"dem":22233,"rep":26029,"total":52258,"name":"Ontario, New York","coordinates":[-77.30349,42.85635]}, {"dem":12100,"rep":37443,"total":52208,"name":"Blount, Tennessee","coordinates":[-83.92297,35.68818]}, {"dem":13256,"rep":35863,"total":52100,"name":"Saline, Arkansas","coordinates":[-92.67446,34.64852]}, {"dem":33480,"rep":13446,"total":51945,"name":"Maui, Hawaii","coordinates":[-156.60155,20.85593]}, {"dem":20965,"rep":27413,"total":51589,"name":"Grand Traverse, Michigan","coordinates":[-85.55384,44.71868]}, {"dem":17200,"rep":31408,"total":51489,"name":"Roanoke, Virginia","coordinates":[-79.94399,37.34358]}, {"dem":17391,"rep":31044,"total":51327,"name":"Fond du Lac, Wisconsin","coordinates":[-88.49328,43.75472]}, {"dem":18706,"rep":28851,"total":51324,"name":"Walworth, Wisconsin","coordinates":[-88.54173,42.6681]}, {"dem":28510,"rep":19010,"total":51191,"name":"Grafton, New Hampshire","coordinates":[-71.84242,43.92643]}, {"dem":18808,"rep":30035,"total":51147,"name":"Clark, Indiana","coordinates":[-85.71112,38.47621]}, {"dem":14846,"rep":33098,"total":50990,"name":"Cass, Missouri","coordinates":[-94.35454,38.64647]}, {"dem":21792,"rep":25747,"total":50823,"name":"Windham, Connecticut","coordinates":[-71.9907,41.82499]}, {"dem":21770,"rep":27540,"total":50689,"name":"Wayne, North Carolina","coordinates":[-78.00866,35.35418]}, {"dem":25709,"rep":19458,"total":50667,"name":"Story, Iowa","coordinates":[-93.46609,42.03753]}, {"dem":11254,"rep":37486,"total":50644,"name":"Morgan, Alabama","coordinates":[-86.8464,34.45448]}, {"dem":13020,"rep":35627,"total":50565,"name":"Lycoming, Pennsylvania","coordinates":[-77.05526,41.34388]}, {"dem":12341,"rep":35430,"total":50113,"name":"Franklin, Missouri","coordinates":[-91.07283,38.413]}, {"dem":31195,"rep":14688,"total":50087,"name":"Douglas, Kansas","coordinates":[-95.29094,38.89641]}, {"dem":17450,"rep":28092,"total":50015,"name":"Cochise, Arizona","coordinates":[-109.77516,31.84012]}, {"dem":17569,"rep":30227,"total":49941,"name":"Geauga, Ohio","coordinates":[-81.1735,41.49932]}, {"dem":15031,"rep":32270,"total":49853,"name":"Wayne, Ohio","coordinates":[-81.88719,40.82966]}, {"dem":12641,"rep":35474,"total":49848,"name":"Bossier, Louisiana","coordinates":[-93.62656,32.69848]}, {"dem":17534,"rep":28663,"total":49842,"name":"St. Mary's, Maryland","coordinates":[-76.53038,38.22028]}, {"dem":20343,"rep":28265,"total":49802,"name":"Madison, Mississippi","coordinates":[-90.03416,32.63437]}, {"dem":13024,"rep":34252,"total":49750,"name":"Washington, Tennessee","coordinates":[-82.49503,36.29566]}, {"dem":19543,"rep":26689,"total":49743,"name":"LaSalle, Illinois","coordinates":[-88.88593,41.34334]}, {"dem":22850,"rep":23460,"total":49721,"name":"Dubuque, Iowa","coordinates":[-90.87877,42.46348]}, {"dem":14657,"rep":33629,"total":49567,"name":"Jackson, Mississippi","coordinates":[-88.6251,30.456]}, {"dem":17281,"rep":29858,"total":49236,"name":"Warren, New Jersey","coordinates":[-75.00949,40.85349]}, {"dem":10025,"rep":36973,"total":49212,"name":"Midland, Texas","coordinates":[-102.00245,31.81426]}, {"dem":10354,"rep":36236,"total":49049,"name":"Pickens, South Carolina","coordinates":[-82.72337,34.88536]}, {"dem":20057,"rep":25933,"total":48885,"name":"Platte, Missouri","coordinates":[-94.76147,39.37869]}, {"dem":30146,"rep":15806,"total":48781,"name":"Wyandotte, Kansas","coordinates":[-94.76308,39.11538]}, {"dem":29193,"rep":13445,"total":48753,"name":"Benton, Oregon","coordinates":[-123.42466,44.49388]}, {"dem":19301,"rep":23250,"total":48753,"name":"Yamhill, Oregon","coordinates":[-123.31639,45.24782]}, {"dem":18750,"rep":28446,"total":48722,"name":"Cape May, New Jersey","coordinates":[-74.84635,39.08584]}, {"dem":16329,"rep":30490,"total":48692,"name":"Moore, North Carolina","coordinates":[-79.49272,35.30827]}, {"dem":19366,"rep":27024,"total":48563,"name":"Putnam, New York","coordinates":[-73.74386,41.4279]}, {"dem":16966,"rep":28673,"total":48454,"name":"Warren, Kentucky","coordinates":[-86.42357,36.99563]}, {"dem":10572,"rep":35070,"total":48326,"name":"Jasper, Missouri","coordinates":[-94.33725,37.20519]}, {"dem":13293,"rep":31053,"total":48283,"name":"Sherburne, Minnesota","coordinates":[-93.76913,45.45317]}, {"dem":17095,"rep":27688,"total":48180,"name":"Oswego, New York","coordinates":[-76.20926,43.46144]}, {"dem":32667,"rep":12704,"total":48091,"name":"Imperial, California","coordinates":[-115.3554,33.04081]}, {"dem":18343,"rep":26866,"total":48060,"name":"Macon, Illinois","coordinates":[-88.96152,39.86023]}, {"dem":10881,"rep":32532,"total":47979,"name":"Burleigh, North Dakota","coordinates":[-100.46953,46.97882]}, {"dem":13242,"rep":32865,"total":47864,"name":"Calhoun, Alabama","coordinates":[-85.8279,33.77051]}, {"dem":14074,"rep":29804,"total":47743,"name":"Pennington, South Dakota","coordinates":[-102.8238,44.00234]}, {"dem":23235,"rep":23319,"total":47665,"name":"Nash, North Carolina","coordinates":[-77.98755,35.96594]}, {"dem":14629,"rep":29346,"total":47527,"name":"Faulkner, Arkansas","coordinates":[-92.33692,35.14654]}, {"dem":17486,"rep":26220,"total":47508,"name":"St. Croix, Wisconsin","coordinates":[-92.44728,45.02895]}, {"dem":14219,"rep":31423,"total":47489,"name":"Adams, Pennsylvania","coordinates":[-77.21772,39.86947]}, {"dem":10301,"rep":35325,"total":47416,"name":"Grayson, Texas","coordinates":[-96.67569,33.62452]}, {"dem":18225,"rep":26176,"total":47408,"name":"Calvert, Maryland","coordinates":[-76.52976,38.52271]}, {"dem":18971,"rep":25129,"total":47305,"name":"Kankakee, Illinois","coordinates":[-87.86111,41.13951]}, {"dem":17630,"rep":27731,"total":47001,"name":"Craven, North Carolina","coordinates":[-77.08131,35.11682]}, {"dem":10869,"rep":34266,"total":46607,"name":"Nassau, Florida","coordinates":[-81.76508,30.60596]}, {"dem":13293,"rep":30240,"total":46571,"name":"Flathead, Montana","coordinates":[-114.05429,48.31467]}, {"dem":12432,"rep":31676,"total":46201,"name":"Columbiana, Ohio","coordinates":[-80.77845,40.77007]}, {"dem":8563,"rep":21139,"total":46157,"name":"Cache, Utah","coordinates":[-111.74539,41.73411]}, {"dem":12865,"rep":27946,"total":46110,"name":"San Juan, New Mexico","coordinates":[-108.32457,36.51162]}, {"dem":16737,"rep":27614,"total":46065,"name":"Harnett, North Carolina","coordinates":[-78.87161,35.36863]}, {"dem":16750,"rep":26430,"total":45939,"name":"Lenawee, Michigan","coordinates":[-84.07435,41.89602]}, {"dem":13294,"rep":30487,"total":45894,"name":"Allen, Ohio","coordinates":[-84.1061,40.77162]}, {"dem":14163,"rep":28907,"total":45807,"name":"Daviess, Kentucky","coordinates":[-87.08713,37.73167]}, {"dem":10085,"rep":33250,"total":45759,"name":"Taylor, Texas","coordinates":[-99.89042,32.29712]}, {"dem":17908,"rep":24185,"total":45692,"name":"Cowlitz, Washington","coordinates":[-122.67845,46.19678]}, {"dem":14937,"rep":29565,"total":45686,"name":"Highlands, Florida","coordinates":[-81.34235,27.34107]}, {"dem":13650,"rep":28868,"total":45269,"name":"Cecil, Maryland","coordinates":[-75.94158,39.56235]}, {"dem":19798,"rep":22687,"total":45203,"name":"LaPorte, Indiana","coordinates":[-86.74473,41.54901]}, {"dem":12734,"rep":30037,"total":45183,"name":"Lapeer, Michigan","coordinates":[-83.22432,43.08863]}, {"dem":18153,"rep":24263,"total":45123,"name":"Delaware, Indiana","coordinates":[-85.39926,40.22754]}, {"dem":29603,"rep":12717,"total":44976,"name":"Clarke, Georgia","coordinates":[-83.36715,33.95218]}, {"dem":14964,"rep":28479,"total":44673,"name":"Cleveland, North Carolina","coordinates":[-81.55711,35.33463]}, {"dem":12300,"rep":29127,"total":44637,"name":"Sebastian, Arkansas","coordinates":[-94.27498,35.19698]}, {"dem":13453,"rep":26923,"total":44560,"name":"Josephine, Oregon","coordinates":[-123.57161,42.38698]}, {"dem":8930,"rep":26699,"total":44221,"name":"Bonneville, Idaho","coordinates":[-111.62187,43.39517]}, {"dem":10442,"rep":32353,"total":44164,"name":"Etowah, Alabama","coordinates":[-86.03426,34.04764]}, {"dem":12464,"rep":30029,"total":44121,"name":"Carroll, Georgia","coordinates":[-85.08052,33.58223]}, {"dem":24047,"rep":18745,"total":44086,"name":"Sumter, South Carolina","coordinates":[-80.38237,33.91613]}, {"dem":21943,"rep":20913,"total":43987,"name":"Newton, Georgia","coordinates":[-83.85518,33.54404]}, {"dem":10665,"rep":31902,"total":43896,"name":"Terrebonne, Louisiana","coordinates":[-90.84367,29.33412]}, {"dem":16210,"rep":24727,"total":43718,"name":"Woodbury, Iowa","coordinates":[-96.05329,42.39321]}, {"dem":20466,"rep":19091,"total":43600,"name":"DeKalb, Illinois","coordinates":[-88.76899,41.89461]}, {"dem":28497,"rep":12795,"total":43265,"name":"Portsmouth, Virginia","coordinates":[-76.35697,36.85933]}, {"dem":23280,"rep":18006,"total":43240,"name":"Suffolk, Virginia","coordinates":[-76.63478,36.69715]}, {"dem":19105,"rep":21306,"total":43173,"name":"James City, Virginia","coordinates":[-76.77788,37.32483]}, {"dem":13944,"rep":26971,"total":43156,"name":"Hardin, Kentucky","coordinates":[-85.96318,37.69583]}, {"dem":16561,"rep":23410,"total":43146,"name":"Jefferson, Wisconsin","coordinates":[-88.77398,43.0138]}, {"dem":17029,"rep":23357,"total":43112,"name":"Madera, California","coordinates":[-119.7498,37.20982]}, {"dem":13968,"rep":26643,"total":43065,"name":"Dodge, Wisconsin","coordinates":[-88.70193,43.42962]}, {"dem":20021,"rep":19459,"total":43031,"name":"Montgomery, Virginia","coordinates":[-80.38779,37.17553]}, {"dem":20960,"rep":18465,"total":42876,"name":"Island, Washington","coordinates":[-122.67064,48.15855]}, {"dem":12321,"rep":28244,"total":42850,"name":"Berkeley, West Virginia","coordinates":[-78.03775,39.44793]}, {"dem":15355,"rep":24447,"total":42680,"name":"Pottawattamie, Iowa","coordinates":[-95.5449,41.34018]}, {"dem":28890,"rep":10371,"total":42678,"name":"Tompkins, New York","coordinates":[-76.47348,42.453]}, {"dem":10664,"rep":30728,"total":42639,"name":"Houston, Alabama","coordinates":[-85.29641,31.15818]}, {"dem":18050,"rep":22198,"total":42547,"name":"Wicomico, Maryland","coordinates":[-75.63208,38.36736]}, {"dem":9768,"rep":30659,"total":42525,"name":"Bedford, Virginia","coordinates":[-79.52722,37.31225]}, {"dem":14658,"rep":25050,"total":42510,"name":"Campbell, Kentucky","coordinates":[-84.37958,38.94698]}, {"dem":15635,"rep":23846,"total":42506,"name":"Midland, Michigan","coordinates":[-84.37941,43.6482]}, {"dem":18971,"rep":21904,"total":42478,"name":"Monroe, Florida","coordinates":[-80.95327,24.76888]}, {"dem":14228,"rep":26830,"total":42278,"name":"Rockingham, North Carolina","coordinates":[-79.78275,36.3818]}, {"dem":12526,"rep":26831,"total":42002,"name":"Steuben, New York","coordinates":[-77.38552,42.26672]}, {"dem":22064,"rep":16876,"total":41895,"name":"Cheshire, New Hampshire","coordinates":[-72.24818,42.92545]}, {"dem":11677,"rep":28764,"total":41749,"name":"Gregg, Texas","coordinates":[-94.81627,32.48639]}, {"dem":8423,"rep":31959,"total":41645,"name":"Lafourche, Louisiana","coordinates":[-90.39484,29.49199]}, {"dem":8508,"rep":30946,"total":41531,"name":"Christian, Missouri","coordinates":[-93.18761,36.96973]}, {"dem":12188,"rep":26918,"total":41289,"name":"Tuscarawas, Ohio","coordinates":[-81.4711,40.44749]}, {"dem":10278,"rep":29587,"total":41265,"name":"Kaufman, Texas","coordinates":[-96.28837,32.59894]}, {"dem":22851,"rep":15077,"total":41045,"name":"Newport, Rhode Island","coordinates":[-71.28368,41.5025]}, {"dem":11573,"rep":24847,"total":40969,"name":"Laramie, Wyoming","coordinates":[-104.66039,41.29283]}, {"dem":15577,"rep":23318,"total":40867,"name":"Ashtabula, Ohio","coordinates":[-80.74559,41.90663]}, {"dem":7902,"rep":30913,"total":40862,"name":"Rogers, Oklahoma","coordinates":[-95.60138,36.37779]}, {"dem":19016,"rep":20762,"total":40858,"name":"Robeson, North Carolina","coordinates":[-79.10088,34.6392]}, {"dem":12311,"rep":26087,"total":40805,"name":"Garland, Arkansas","coordinates":[-93.14693,34.57885]}, {"dem":14009,"rep":25428,"total":40753,"name":"Lawrence, Pennsylvania","coordinates":[-80.33444,40.99273]}, {"dem":8292,"rep":31125,"total":40698,"name":"Walton, Georgia","coordinates":[-83.73182,33.78388]}, {"dem":16492,"rep":21636,"total":40655,"name":"Clinton, Michigan","coordinates":[-84.59169,42.95045]}, {"dem":11932,"rep":26083,"total":40440,"name":"Frederick, Virginia","coordinates":[-78.26382,39.20366]}, {"dem":14506,"rep":23193,"total":40346,"name":"Manitowoc, Wisconsin","coordinates":[-87.57735,44.15613]}, {"dem":16420,"rep":18940,"total":40295,"name":"Polk, Oregon","coordinates":[-123.39867,44.90037]}, {"dem":9468,"rep":29067,"total":40294,"name":"Limestone, Alabama","coordinates":[-86.98139,34.81023]}, {"dem":16459,"rep":20577,"total":40294,"name":"Navajo, Arizona","coordinates":[-110.32102,35.39078]}, {"dem":9897,"rep":28806,"total":40023,"name":"Lincoln, North Carolina","coordinates":[-81.22689,35.48849]}, {"dem":17209,"rep":21971,"total":39977,"name":"St. Landry, Louisiana","coordinates":[-91.98927,30.58344]}, {"dem":9655,"rep":28451,"total":39948,"name":"Rockwall, Texas","coordinates":[-96.4044,32.89867]}, {"dem":21065,"rep":17105,"total":39849,"name":"Chatham, North Carolina","coordinates":[-79.25145,35.70499]}, {"dem":15931,"rep":21937,"total":39818,"name":"Vigo, Indiana","coordinates":[-87.39037,39.42914]}, {"dem":13473,"rep":23380,"total":39687,"name":"Wayne, New York","coordinates":[-77.06316,43.45875]}, {"dem":8212,"rep":29911,"total":39550,"name":"Bartow, Georgia","coordinates":[-84.83818,34.24091]}, {"dem":9952,"rep":27899,"total":39525,"name":"Lauderdale, Alabama","coordinates":[-87.65099,34.90412]}, {"dem":17677,"rep":18794,"total":39457,"name":"Clallam, Washington","coordinates":[-123.88985,48.1109]}, {"dem":16488,"rep":19942,"total":39158,"name":"St. Lawrence, New York","coordinates":[-75.07431,44.48811]}, {"dem":13812,"rep":23719,"total":38938,"name":"Lancaster, South Carolina","coordinates":[-80.70368,34.68681]}, {"dem":11251,"rep":26238,"total":38920,"name":"Burke, North Carolina","coordinates":[-81.70617,35.74618]}, {"dem":26318,"rep":11931,"total":38910,"name":"Orangeburg, South Carolina","coordinates":[-80.80291,33.43613]}, {"dem":7070,"rep":29768,"total":38666,"name":"Bradley, Tennessee","coordinates":[-84.85941,35.15391]}, {"dem":18521,"rep":17306,"total":38496,"name":"Portage, Wisconsin","coordinates":[-89.49806,44.47624]}, {"dem":9173,"rep":27494,"total":38479,"name":"Tom Green, Texas","coordinates":[-100.46378,31.39882]}, {"dem":5589,"rep":31651,"total":38400,"name":"St. Clair, Alabama","coordinates":[-86.31566,33.71296]}, {"dem":15701,"rep":19339,"total":38252,"name":"Dallas, Iowa","coordinates":[-94.0407,41.68532]}, {"dem":13809,"rep":21763,"total":38236,"name":"Jefferson, New York","coordinates":[-76.05296,43.99638]}, {"dem":24478,"rep":10364,"total":38177,"name":"Franklin, Massachusetts","coordinates":[-72.59179,42.5845]}, {"dem":19663,"rep":17531,"total":38135,"name":"Wilson, North Carolina","coordinates":[-77.92159,35.70035]}, {"dem":15448,"rep":21335,"total":38120,"name":"Madison, Tennessee","coordinates":[-88.83342,35.60605]}, {"dem":8770,"rep":27631,"total":38119,"name":"Wichita, Texas","coordinates":[-98.708,33.98821]}, {"dem":3798,"rep":32989,"total":37873,"name":"Cullman, Alabama","coordinates":[-86.86926,34.13192]}, {"dem":23255,"rep":13478,"total":37869,"name":"Rockdale, Georgia","coordinates":[-84.02636,33.65208]}, {"dem":15064,"rep":21635,"total":37805,"name":"Lowndes, Georgia","coordinates":[-83.26899,30.83314]}, {"dem":14232,"rep":21503,"total":37800,"name":"Wood, Wisconsin","coordinates":[-90.03882,44.46141]}, {"dem":9939,"rep":26569,"total":37781,"name":"Carteret, North Carolina","coordinates":[-76.53586,34.85834]}, {"dem":11528,"rep":24888,"total":37770,"name":"Indiana, Pennsylvania","coordinates":[-79.08754,40.65143]}, {"dem":16057,"rep":19648,"total":37578,"name":"Erie, Ohio","coordinates":[-82.52589,41.554]}, {"dem":10971,"rep":24987,"total":37492,"name":"Crawford, Pennsylvania","coordinates":[-80.10779,41.68787]}, {"dem":9366,"rep":25990,"total":37487,"name":"Rockingham, Virginia","coordinates":[-78.88532,38.50758]}, {"dem":22079,"rep":10888,"total":37477,"name":"Mendocino, California","coordinates":[-123.44288,39.43238]}, {"dem":12971,"rep":22127,"total":37467,"name":"Fauquier, Virginia","coordinates":[-77.8215,38.74409]}, {"dem":13945,"rep":21432,"total":37425,"name":"Floyd, Indiana","coordinates":[-85.91184,38.31808]}, {"dem":10913,"rep":24616,"total":37374,"name":"Cole, Missouri","coordinates":[-92.28002,38.50323]}, {"dem":11793,"rep":23431,"total":37371,"name":"Madison, Kentucky","coordinates":[-84.27836,37.72551]}, {"dem":8443,"rep":27634,"total":37260,"name":"Elmore, Alabama","coordinates":[-86.14273,32.59722]}, {"dem":8492,"rep":27017,"total":37038,"name":"Cape Girardeau, Missouri","coordinates":[-89.68565,37.38414]}, {"dem":11123,"rep":24056,"total":36991,"name":"Muskingum, Ohio","coordinates":[-81.9435,39.96604]}, {"dem":11215,"rep":23675,"total":36843,"name":"Howard, Indiana","coordinates":[-86.11411,40.48353]}, {"dem":9788,"rep":25427,"total":36622,"name":"Northumberland, Pennsylvania","coordinates":[-76.70987,40.85152]}, {"dem":10249,"rep":25020,"total":36530,"name":"Ector, Texas","coordinates":[-102.5425,31.8653]}, {"dem":8177,"rep":26163,"total":36343,"name":"Augusta, Virginia","coordinates":[-79.14755,38.17191]}, {"dem":8425,"rep":26621,"total":36320,"name":"Caldwell, North Carolina","coordinates":[-81.51254,35.96639]}, {"dem":6297,"rep":28629,"total":36312,"name":"Sevier, Tennessee","coordinates":[-83.51849,35.79534]}, {"dem":8904,"rep":25074,"total":36181,"name":"Hancock, Indiana","coordinates":[-85.77315,39.82252]}, {"dem":13757,"rep":20097,"total":36119,"name":"Chemung, New York","coordinates":[-76.74717,42.15528]}, {"dem":8255,"rep":26210,"total":36069,"name":"Bullitt, Kentucky","coordinates":[-85.70263,37.96994]}, {"dem":14699,"rep":18432,"total":36048,"name":"Monongalia, West Virginia","coordinates":[-80.05907,39.63364]}, {"dem":9609,"rep":24183,"total":36023,"name":"Hancock, Ohio","coordinates":[-83.66603,41.00047]}, {"dem":10982,"rep":22287,"total":35842,"name":"Crow Wing, Minnesota","coordinates":[-94.07071,46.49165]}, {"dem":7376,"rep":27379,"total":35773,"name":"Somerset, Pennsylvania","coordinates":[-79.02848,39.98129]}, {"dem":14792,"rep":17982,"total":35671,"name":"Lynchburg, Virginia","coordinates":[-79.19545,37.39901]}, {"dem":12013,"rep":21320,"total":35659,"name":"Buchanan, Missouri","coordinates":[-94.80817,39.66036]}, {"dem":8400,"rep":25434,"total":35615,"name":"Wood, West Virginia","coordinates":[-81.51623,39.2116]}, {"dem":10538,"rep":22892,"total":35573,"name":"Craighead, Arkansas","coordinates":[-90.63142,35.82772]}, {"dem":10038,"rep":23799,"total":35369,"name":"Maury, Tennessee","coordinates":[-87.07776,35.61569]}, {"dem":4917,"rep":29233,"total":35316,"name":"Marshall, Alabama","coordinates":[-86.32166,34.30956]}, {"dem":13386,"rep":19419,"total":35097,"name":"Aroostook, Maine","coordinates":[-68.6124,46.70919]}, {"dem":13517,"rep":19315,"total":35045,"name":"Belknap, New Hampshire","coordinates":[-71.42536,43.5191]}, {"dem":9159,"rep":24114,"total":34608,"name":"Floyd, Georgia","coordinates":[-85.21368,34.26369]}, {"dem":8838,"rep":24924,"total":34602,"name":"Bowie, Texas","coordinates":[-94.42239,33.44606]}, {"dem":12175,"rep":19632,"total":34571,"name":"Cascade, Montana","coordinates":[-111.35026,47.31657]}, {"dem":14478,"rep":16895,"total":34478,"name":"Lewis and Clark, Montana","coordinates":[-112.37336,47.13201]}, {"dem":8200,"rep":24932,"total":34271,"name":"Clearfield, Pennsylvania","coordinates":[-78.47374,41.00024]}, {"dem":11775,"rep":21512,"total":34263,"name":"Glynn, Georgia","coordinates":[-81.49645,31.2127]}, {"dem":9654,"rep":21992,"total":34149,"name":"Lewis, Washington","coordinates":[-122.37744,46.58007]}, {"dem":12999,"rep":18837,"total":34118,"name":"York, Virginia","coordinates":[-76.56164,37.21908]}, {"dem":12546,"rep":19230,"total":34111,"name":"Shiawassee, Michigan","coordinates":[-84.14635,42.95154]}, {"dem":23311,"rep":10232,"total":34087,"name":"Dougherty, Georgia","coordinates":[-84.20904,31.53258]}, {"dem":13617,"rep":18093,"total":33915,"name":"Kings, California","coordinates":[-119.81553,36.07247]}, {"dem":6876,"rep":25756,"total":33637,"name":"Walton, Florida","coordinates":[-86.17661,30.63121]}, {"dem":7998,"rep":24178,"total":33635,"name":"Oconee, South Carolina","coordinates":[-83.06153,34.74876]}, {"dem":14428,"rep":15667,"total":33593,"name":"Blue Earth, Minnesota","coordinates":[-94.06401,44.03371]}, {"dem":13076,"rep":18176,"total":33523,"name":"Sutter, California","coordinates":[-121.70393,39.03618]}, {"dem":10342,"rep":17180,"total":33416,"name":"Bannock, Idaho","coordinates":[-112.22898,42.69292]}, {"dem":12121,"rep":20614,"total":33407,"name":"Talladega, Alabama","coordinates":[-86.17593,33.36931]}, {"dem":13032,"rep":18114,"total":33380,"name":"Chelan, Washington","coordinates":[-120.61904,47.86097]}, {"dem":6577,"rep":23552,"total":33348,"name":"Natrona, Wyoming","coordinates":[-106.76821,42.97764]}, {"dem":13258,"rep":17890,"total":33274,"name":"Van Buren, Michigan","coordinates":[-86.30607,42.28214]}, {"dem":13522,"rep":17384,"total":33172,"name":"Cayuga, New York","coordinates":[-76.57458,43.00854]}, {"dem":10094,"rep":22138,"total":33117,"name":"Putnam, Florida","coordinates":[-81.73203,29.59389]}, {"dem":11447,"rep":19850,"total":33085,"name":"Cabell, West Virginia","coordinates":[-82.24339,38.41957]}, {"dem":16042,"rep":14646,"total":32976,"name":"Marquette, Michigan","coordinates":[-87.58402,46.65659]}, {"dem":10029,"rep":22220,"total":32913,"name":"Lee, Mississippi","coordinates":[-88.68243,34.29237]}, {"dem":10268,"rep":20469,"total":32853,"name":"Oldham, Kentucky","coordinates":[-85.45615,38.40012]}, {"dem":11463,"rep":19183,"total":32564,"name":"Comanche, Oklahoma","coordinates":[-98.47661,34.66263]}, {"dem":9340,"rep":20939,"total":32500,"name":"Otter Tail, Minnesota","coordinates":[-95.71458,46.40572]}, {"dem":9841,"rep":20640,"total":32490,"name":"Bartholomew, Indiana","coordinates":[-85.89799,39.20584]}, {"dem":10698,"rep":20903,"total":32454,"name":"Iberia, Louisiana","coordinates":[-91.97678,30.00712]}, {"dem":14437,"rep":15429,"total":32443,"name":"Rice, Minnesota","coordinates":[-93.2985,44.35073]}, {"dem":9675,"rep":21117,"total":32201,"name":"Jefferson, Ohio","coordinates":[-80.76352,40.39938]}, {"dem":7488,"rep":23671,"total":32196,"name":"Surry, North Carolina","coordinates":[-80.68646,36.41541]}, {"dem":10181,"rep":19654,"total":32178,"name":"Boone, Indiana","coordinates":[-86.46901,40.05089]}, {"dem":16117,"rep":13705,"total":32130,"name":"Hancock, Maine","coordinates":[-68.3707,44.5649]}, {"dem":15059,"rep":14449,"total":32105,"name":"Clinton, New York","coordinates":[-73.70564,44.75271]}, {"dem":6313,"rep":23935,"total":32084,"name":"Kosciusko, Indiana","coordinates":[-85.86157,41.24429]}, {"dem":5735,"rep":25513,"total":32000,"name":"Orange, Texas","coordinates":[-93.89409,30.12232]}, {"dem":7676,"rep":22790,"total":31951,"name":"Adams, Illinois","coordinates":[-91.19496,39.98605]}, {"dem":8581,"rep":21570,"total":31852,"name":"Williamson, Illinois","coordinates":[-88.93001,37.73035]}, {"dem":13310,"rep":17389,"total":31657,"name":"Georgetown, South Carolina","coordinates":[-79.29633,33.41753]}, {"dem":7178,"rep":23484,"total":31618,"name":"Armstrong, Pennsylvania","coordinates":[-79.46412,40.81238]}, {"dem":9199,"rep":21554,"total":31598,"name":"Pittsylvania, Virginia","coordinates":[-79.3985,36.82172]}, {"dem":11886,"rep":17909,"total":31561,"name":"Chippewa, Wisconsin","coordinates":[-91.2835,45.06909]}, {"dem":6396,"rep":23910,"total":31554,"name":"Hunt, Texas","coordinates":[-96.08422,33.1233]}, {"dem":13091,"rep":15751,"total":31408,"name":"Warren, New York","coordinates":[-73.83813,43.5551]}, {"dem":14692,"rep":14791,"total":31318,"name":"Sauk, Wisconsin","coordinates":[-89.94331,43.428]}, {"dem":10448,"rep":17865,"total":31313,"name":"Coos, Oregon","coordinates":[-124.09413,43.1859]}, {"dem":9134,"rep":20774,"total":31307,"name":"McCracken, Kentucky","coordinates":[-88.71245,37.05411]}, {"dem":6723,"rep":23005,"total":31300,"name":"Wagoner, Oklahoma","coordinates":[-95.51409,35.96347]}, {"dem":6638,"rep":23752,"total":31296,"name":"Wilkes, North Carolina","coordinates":[-81.16609,36.20888]}, {"dem":6040,"rep":23674,"total":31280,"name":"Morgan, Indiana","coordinates":[-86.44745,39.48264]}, {"dem":12172,"rep":16210,"total":31201,"name":"Oxford, Maine","coordinates":[-70.73442,44.49449]}, {"dem":9497,"rep":19692,"total":31161,"name":"Cattaraugus, New York","coordinates":[-78.66233,42.23909]}, {"dem":15525,"rep":12587,"total":31150,"name":"La Plata, Colorado","coordinates":[-107.83971,37.28736]}, {"dem":8866,"rep":21275,"total":31123,"name":"Victoria, Texas","coordinates":[-96.97119,28.79636]}, {"dem":8785,"rep":21108,"total":31122,"name":"Belmont, Ohio","coordinates":[-80.96772,40.01768]}, {"dem":18594,"rep":7993,"total":31086,"name":"Washington, Vermont","coordinates":[-72.60951,44.27498]}, {"dem":15284,"rep":13756,"total":30902,"name":"Columbia, New York","coordinates":[-73.6268,42.24772]}, {"dem":9132,"rep":20550,"total":30784,"name":"Scioto, Ohio","coordinates":[-82.99867,38.81488]}, {"dem":10473,"rep":18929,"total":30727,"name":"Haywood, North Carolina","coordinates":[-82.9813,35.55888]}, {"dem":7937,"rep":21537,"total":30658,"name":"Whitfield, Georgia","coordinates":[-84.96854,34.80172]}, {"dem":7875,"rep":21270,"total":30654,"name":"Allegany, Maryland","coordinates":[-78.7031,39.61231]}, {"dem":10039,"rep":19087,"total":30570,"name":"Vermilion, Illinois","coordinates":[-87.72677,40.18675]}, {"dem":7210,"rep":20435,"total":30507,"name":"Klamath, Oregon","coordinates":[-121.64616,42.68376]}, {"dem":10356,"rep":18652,"total":30380,"name":"Ross, Ohio","coordinates":[-83.05953,39.32389]}, {"dem":12874,"rep":16368,"total":30368,"name":"Franklin, North Carolina","coordinates":[-78.28309,36.08824]}, {"dem":10851,"rep":16340,"total":30365,"name":"Grand Forks, North Dakota","coordinates":[-97.45085,47.926]}, {"dem":9114,"rep":19202,"total":30329,"name":"Barry, Michigan","coordinates":[-85.31455,42.58281]}, {"dem":7512,"rep":21871,"total":30307,"name":"Rutherford, North Carolina","coordinates":[-81.91958,35.40274]}, {"dem":10209,"rep":17638,"total":30301,"name":"Leavenworth, Kansas","coordinates":[-95.03897,39.18951]}, {"dem":9278,"rep":18441,"total":30228,"name":"Chisago, Minnesota","coordinates":[-92.90384,45.50544]}, {"dem":11667,"rep":15936,"total":30064,"name":"Madison, New York","coordinates":[-75.66357,42.91002]}, {"dem":5669,"rep":23650,"total":30045,"name":"Henderson, Texas","coordinates":[-95.85341,32.21163]}, {"dem":10697,"rep":17290,"total":30031,"name":"Livingston, New York","coordinates":[-77.76977,42.72748]}, {"dem":14138,"rep":13697,"total":29985,"name":"Watauga, North Carolina","coordinates":[-81.70988,36.23536]}, {"dem":12568,"rep":15931,"total":29955,"name":"Sullivan, New York","coordinates":[-74.77157,41.71999]}, {"dem":17556,"rep":8605,"total":29928,"name":"Windsor, Vermont","coordinates":[-72.59882,43.57268]}, {"dem":7094,"rep":21964,"total":29917,"name":"Stanly, North Carolina","coordinates":[-80.25437,35.31044]}, {"dem":7538,"rep":21668,"total":29911,"name":"Angelina, Texas","coordinates":[-94.61113,31.25189]}, {"dem":9013,"rep":19212,"total":29881,"name":"Anderson, Tennessee","coordinates":[-84.19541,36.11673]}, {"dem":6233,"rep":19828,"total":29874,"name":"Twin Falls, Idaho","coordinates":[-114.66563,42.3523]}, {"dem":8026,"rep":20514,"total":29840,"name":"Washington, Ohio","coordinates":[-81.49063,39.45067]}, {"dem":13526,"rep":14160,"total":29771,"name":"Columbia, Wisconsin","coordinates":[-89.33047,43.47188]}, {"dem":13888,"rep":14989,"total":29674,"name":"Darlington, South Carolina","coordinates":[-79.96211,34.33218]}, {"dem":13635,"rep":12479,"total":29619,"name":"Rutland, Vermont","coordinates":[-73.0382,43.58085]}, {"dem":6443,"rep":22048,"total":29618,"name":"Raleigh, West Virginia","coordinates":[-81.26467,37.76246]}, {"dem":12987,"rep":14635,"total":29616,"name":"Carroll, New Hampshire","coordinates":[-71.20155,43.86777]}, {"dem":9086,"rep":19113,"total":29589,"name":"Warrick, Indiana","coordinates":[-87.27204,38.09772]}, {"dem":11269,"rep":17741,"total":29506,"name":"Lauderdale, Mississippi","coordinates":[-88.66044,32.40399]}, {"dem":11904,"rep":16381,"total":29494,"name":"Salem, New Jersey","coordinates":[-75.35735,39.57382]}, {"dem":4497,"rep":24266,"total":29472,"name":"Walker, Alabama","coordinates":[-87.30109,33.79155]}, {"dem":16370,"rep":11354,"total":29443,"name":"Athens, Ohio","coordinates":[-82.04584,39.3326]}, {"dem":12971,"rep":13543,"total":29398,"name":"Clay, Minnesota","coordinates":[-96.4949,46.89837]}, {"dem":6580,"rep":21108,"total":29060,"name":"Barrow, Georgia","coordinates":[-83.7123,33.992]}, {"dem":10330,"rep":17542,"total":28995,"name":"Kershaw, South Carolina","coordinates":[-80.59088,34.33835]}, {"dem":5841,"rep":21575,"total":28830,"name":"Creek, Oklahoma","coordinates":[-96.37979,35.90773]}, {"dem":8936,"rep":18743,"total":28776,"name":"Carbon, Pennsylvania","coordinates":[-75.70503,40.91836]}, {"dem":10711,"rep":16961,"total":28763,"name":"Greenwood, South Carolina","coordinates":[-82.12787,34.15579]}, {"dem":7601,"rep":20368,"total":28707,"name":"Columbia, Florida","coordinates":[-82.62337,30.22165]}, {"dem":8171,"rep":19131,"total":28687,"name":"Knox, Ohio","coordinates":[-82.42239,40.40361]}, {"dem":7657,"rep":19630,"total":28651,"name":"Potter, Texas","coordinates":[-101.8938,35.39867]}, {"dem":10569,"rep":16328,"total":28454,"name":"Bastrop, Texas","coordinates":[-97.31063,30.10077]}, {"dem":12020,"rep":14067,"total":28367,"name":"Grays Harbor, Washington","coordinates":[-123.82673,47.11373]}, {"dem":7791,"rep":20133,"total":28352,"name":"Jones, Mississippi","coordinates":[-89.16853,31.6166]}, {"dem":7810,"rep":18518,"total":28346,"name":"Grant, Washington","coordinates":[-119.46778,47.21363]}, {"dem":9753,"rep":17210,"total":28273,"name":"Worcester, Maryland","coordinates":[-75.30993,38.22213]}, {"dem":8934,"rep":18004,"total":28228,"name":"Columbia, Pennsylvania","coordinates":[-76.40425,41.04551]}, {"dem":11993,"rep":13677,"total":28073,"name":"Mason, Washington","coordinates":[-123.17384,47.35412]}, {"dem":11716,"rep":15461,"total":28064,"name":"Forrest, Mississippi","coordinates":[-89.25944,31.18858]}, {"dem":9929,"rep":16316,"total":28044,"name":"Sandusky, Ohio","coordinates":[-83.14277,41.35531]}, {"dem":4208,"rep":22902,"total":28041,"name":"Pulaski, Kentucky","coordinates":[-84.57695,37.10737]}, {"dem":7694,"rep":18750,"total":27960,"name":"Harrison, West Virginia","coordinates":[-80.38649,39.27918]}, {"dem":8454,"rep":17415,"total":27885,"name":"Douglas, Nevada","coordinates":[-119.60901,38.90512]}, {"dem":9354,"rep":17639,"total":27885,"name":"Pender, North Carolina","coordinates":[-77.8881,34.51255]}, {"dem":8788,"rep":16651,"total":27760,"name":"Payne, Oklahoma","coordinates":[-96.97525,36.07922]}, {"dem":17083,"rep":8240,"total":27661,"name":"Apache, Arizona","coordinates":[-109.49017,35.38508]}, {"dem":6573,"rep":19073,"total":27657,"name":"Butler, Kansas","coordinates":[-96.83884,37.77364]}, {"dem":7673,"rep":17059,"total":27597,"name":"Umatilla, Oregon","coordinates":[-118.73387,45.59119]}, {"dem":10841,"rep":13215,"total":27592,"name":"Valencia, New Mexico","coordinates":[-106.80658,34.71684]}, {"dem":6664,"rep":19551,"total":27535,"name":"Campbell, Virginia","coordinates":[-79.09542,37.21015]}, {"dem":7718,"rep":18096,"total":27429,"name":"Union, Ohio","coordinates":[-83.36704,40.2959]}, {"dem":5806,"rep":18636,"total":27412,"name":"Ward, North Dakota","coordinates":[-101.54053,48.21668]}, {"dem":5638,"rep":21162,"total":27389,"name":"Acadia, Louisiana","coordinates":[-92.41103,30.29149]}, {"dem":12909,"rep":13591,"total":27353,"name":"Granville, North Carolina","coordinates":[-78.65763,36.29988]}, {"dem":10411,"rep":14814,"total":27300,"name":"Warren, Iowa","coordinates":[-93.56875,41.33244]}, {"dem":5170,"rep":21077,"total":27219,"name":"White, Arkansas","coordinates":[-91.75303,35.25511]}, {"dem":6851,"rep":19002,"total":27212,"name":"Putnam, Tennessee","coordinates":[-85.49618,36.14094]}, {"dem":4491,"rep":21784,"total":27190,"name":"Jackson, Georgia","coordinates":[-83.56255,34.1309]}, {"dem":6637,"rep":19410,"total":27113,"name":"Robertson, Tennessee","coordinates":[-86.86935,36.5275]}, {"dem":5664,"rep":19958,"total":27100,"name":"Lonoke, Arkansas","coordinates":[-91.89413,34.75511]}, {"dem":7257,"rep":18569,"total":26971,"name":"Franklin, Virginia","coordinates":[-79.88271,36.99118]}, {"dem":8352,"rep":16635,"total":26854,"name":"Ionia, Michigan","coordinates":[-85.07376,42.94465]}, {"dem":12634,"rep":13613,"total":26807,"name":"Lenoir, North Carolina","coordinates":[-77.6355,35.24006]}, {"dem":4771,"rep":20876,"total":26757,"name":"Catoosa, Georgia","coordinates":[-85.13938,34.90021]}, {"dem":9646,"rep":15348,"total":26650,"name":"Calumet, Wisconsin","coordinates":[-88.21213,44.07841]}, {"dem":10167,"rep":13217,"total":26618,"name":"Columbia, Oregon","coordinates":[-123.08107,45.94193]}, {"dem":7874,"rep":16907,"total":26609,"name":"Montcalm, Michigan","coordinates":[-85.14946,43.31278]}, {"dem":6974,"rep":18689,"total":26607,"name":"Lawrence, Ohio","coordinates":[-82.51718,38.60386]}, {"dem":4990,"rep":20553,"total":26606,"name":"Newton, Missouri","coordinates":[-94.33503,36.90837]}, {"dem":8889,"rep":16816,"total":26566,"name":"Laurens, South Carolina","coordinates":[-82.00549,34.48367]}, {"dem":7151,"rep":18749,"total":26548,"name":"Harrison, Texas","coordinates":[-94.37443,32.54799]}, {"dem":7973,"rep":16993,"total":26523,"name":"Queen Anne's, Maryland","coordinates":[-76.0824,39.04069]}, {"dem":11271,"rep":13132,"total":26470,"name":"Garfield, Colorado","coordinates":[-107.90978,39.59935]}, {"dem":7650,"rep":16915,"total":26432,"name":"Genesee, New York","coordinates":[-78.19277,43.0009]}, {"dem":5202,"rep":20413,"total":26360,"name":"Cumberland, Tennessee","coordinates":[-84.99476,35.95239]}, {"dem":16456,"rep":7574,"total":26335,"name":"Kauai, Hawaii","coordinates":[-159.70596,22.01203]}, {"dem":7928,"rep":16961,"total":26322,"name":"Marion, Ohio","coordinates":[-83.1688,40.58803]}, {"dem":4008,"rep":21382,"total":26262,"name":"Hood, Texas","coordinates":[-97.83167,32.43014]}, {"dem":8083,"rep":16699,"total":26255,"name":"Herkimer, New York","coordinates":[-75.01168,43.40748]}, {"dem":8559,"rep":16621,"total":26192,"name":"St. Charles, Louisiana","coordinates":[-90.35785,29.90572]}, {"dem":9713,"rep":15750,"total":26111,"name":"Troup, Georgia","coordinates":[-85.02835,33.03448]}, {"dem":9256,"rep":16056,"total":26101,"name":"Pike, Pennsylvania","coordinates":[-75.03151,41.32594]}, {"dem":11366,"rep":12122,"total":26074,"name":"Winona, Minnesota","coordinates":[-91.7767,43.98226]}, {"dem":9092,"rep":15001,"total":26064,"name":"Somerset, Maine","coordinates":[-69.9561,45.50364]}, {"dem":8440,"rep":16189,"total":26024,"name":"Waupaca, Wisconsin","coordinates":[-88.967,44.478]}, {"dem":10547,"rep":14838,"total":25928,"name":"Sampson, North Carolina","coordinates":[-78.37117,34.98929]}, {"dem":15772,"rep":9250,"total":25894,"name":"Jefferson, Arkansas","coordinates":[-91.92967,34.27723]}, {"dem":5553,"rep":19320,"total":25847,"name":"Washington, Virginia","coordinates":[-81.95032,36.74781]}, {"dem":3622,"rep":21405,"total":25826,"name":"DeKalb, Alabama","coordinates":[-85.80399,34.46092]}, {"dem":7429,"rep":17102,"total":25796,"name":"Tuscola, Michigan","coordinates":[-83.43661,43.4879]}, {"dem":8266,"rep":16873,"total":25750,"name":"St. Martin, Louisiana","coordinates":[-91.61148,30.12143]}, {"dem":9446,"rep":14041,"total":25717,"name":"Goodhue, Minnesota","coordinates":[-92.716,44.40617]}, {"dem":6369,"rep":18141,"total":25708,"name":"Bradford, Pennsylvania","coordinates":[-76.50212,41.7915]}, {"dem":9357,"rep":15646,"total":25704,"name":"Spalding, Georgia","coordinates":[-84.2849,33.26234]}, {"dem":10451,"rep":13308,"total":25668,"name":"Otsego, New York","coordinates":[-75.02884,42.62977]}, {"dem":4857,"rep":20063,"total":25632,"name":"Vermilion, Louisiana","coordinates":[-92.29156,29.78972]}, {"dem":2156,"rep":22859,"total":25588,"name":"Blount, Alabama","coordinates":[-86.56644,33.97735]}, {"dem":11035,"rep":12615,"total":25582,"name":"Whiteside, Illinois","coordinates":[-89.911,41.75067]}, {"dem":8322,"rep":16028,"total":25579,"name":"Wayne, Indiana","coordinates":[-85.00673,39.86309]}, {"dem":11819,"rep":13271,"total":25575,"name":"Lowndes, Mississippi","coordinates":[-88.43972,33.47142]}, {"dem":9123,"rep":14551,"total":25529,"name":"Tuolumne, California","coordinates":[-119.96473,38.02143]}, {"dem":4470,"rep":20012,"total":25484,"name":"Darke, Ohio","coordinates":[-84.62124,40.13154]}, {"dem":14609,"rep":8965,"total":25475,"name":"Bristol, Rhode Island","coordinates":[-71.28663,41.70683]}, {"dem":6015,"rep":17848,"total":25452,"name":"Pottawatomie, Oklahoma","coordinates":[-96.957,35.21139]}, {"dem":9694,"rep":13651,"total":25419,"name":"Walla Walla, Washington","coordinates":[-118.48036,46.2546]}, {"dem":11404,"rep":12338,"total":25392,"name":"Isabella, Michigan","coordinates":[-84.83942,43.64523]}, {"dem":9261,"rep":15097,"total":25316,"name":"Bulloch, Georgia","coordinates":[-81.74402,32.39171]}, {"dem":7010,"rep":17008,"total":25312,"name":"Grant, Indiana","coordinates":[-85.65494,40.51575]}, {"dem":12501,"rep":10039,"total":25256,"name":"Lincoln, Oregon","coordinates":[-123.91121,44.64106]}, {"dem":8076,"rep":15499,"total":25231,"name":"Lincoln, South Dakota","coordinates":[-96.72228,43.27942]}, {"dem":14099,"rep":8990,"total":25223,"name":"Eagle, Colorado","coordinates":[-106.69516,39.62699]}, {"dem":15748,"rep":9031,"total":25167,"name":"Halifax, North Carolina","coordinates":[-77.64484,36.25143]}, {"dem":10469,"rep":13712,"total":25084,"name":"Lee, North Carolina","coordinates":[-79.17211,35.47633]}, {"dem":9610,"rep":13125,"total":25016,"name":"Carson City, Nevada","coordinates":[-119.74736,39.15305]}, {"dem":5936,"rep":18172,"total":24973,"name":"Autauga, Alabama","coordinates":[-86.64643,32.53223]}, {"dem":5575,"rep":18159,"total":24962,"name":"Lincoln, Missouri","coordinates":[-90.96291,39.06225]}, {"dem":7312,"rep":16746,"total":24915,"name":"Colbert, Alabama","coordinates":[-87.80145,34.70311]}, {"dem":5884,"rep":17788,"total":24893,"name":"Putnam, West Virginia","coordinates":[-81.9061,38.51051]}, {"dem":16224,"rep":8261,"total":24886,"name":"Edgecombe, North Carolina","coordinates":[-77.60274,35.91707]}, {"dem":7192,"rep":16226,"total":24834,"name":"Huron, Ohio","coordinates":[-82.59464,41.14507]}, {"dem":3440,"rep":20592,"total":24833,"name":"Laurel, Kentucky","coordinates":[-84.11939,37.11326]}, {"dem":3412,"rep":20670,"total":24776,"name":"Wise, Texas","coordinates":[-97.65399,33.21909]}, {"dem":6529,"rep":17076,"total":24745,"name":"Pickaway, Ohio","coordinates":[-83.05282,39.64894]}, {"dem":6250,"rep":17468,"total":24728,"name":"St. Francois, Missouri","coordinates":[-90.47386,37.8107]}, {"dem":4280,"rep":19747,"total":24665,"name":"Pike, Kentucky","coordinates":[-82.41091,37.48603]}, {"dem":8871,"rep":13985,"total":24643,"name":"Henry, Illinois","coordinates":[-90.13083,41.35002]}, {"dem":11634,"rep":10843,"total":24617,"name":"Jackson, Illinois","coordinates":[-89.38121,37.78609]}, {"dem":5190,"rep":18751,"total":24592,"name":"Lamar, Mississippi","coordinates":[-89.50636,31.19758]}, {"dem":5740,"rep":17493,"total":24590,"name":"Ashland, Ohio","coordinates":[-82.27012,40.84327]}, {"dem":9098,"rep":13610,"total":24528,"name":"Washington, New York","coordinates":[-73.43942,43.31237]}, {"dem":11496,"rep":10599,"total":24496,"name":"Lake, California","coordinates":[-122.74675,39.0948]}, {"dem":10046,"rep":12349,"total":24321,"name":"Grant, Wisconsin","coordinates":[-90.69422,42.87002]}, {"dem":4862,"rep":18892,"total":24267,"name":"Liberty, Texas","coordinates":[-94.84406,30.1585]}, {"dem":7977,"rep":15043,"total":24216,"name":"Muskogee, Oklahoma","coordinates":[-95.38391,35.61755]}, {"dem":6837,"rep":15513,"total":24210,"name":"Reno, Kansas","coordinates":[-98.07834,37.94818]}, {"dem":7715,"rep":15052,"total":24200,"name":"Scott, Kentucky","coordinates":[-84.57834,38.2857]}, {"dem":8050,"rep":14352,"total":24193,"name":"Ogle, Illinois","coordinates":[-89.32017,42.04188]}, {"dem":9518,"rep":13204,"total":24147,"name":"Jefferson, West Virginia","coordinates":[-77.86322,39.30739]}, {"dem":8198,"rep":15208,"total":24106,"name":"Henry, Virginia","coordinates":[-79.75923,36.78147]}, {"dem":7008,"rep":16244,"total":24018,"name":"Wayne, Pennsylvania","coordinates":[-75.29249,41.6466]}, {"dem":4883,"rep":18113,"total":23987,"name":"Dearborn, Indiana","coordinates":[-84.97349,39.14832]}, {"dem":7404,"rep":14825,"total":23987,"name":"Seneca, Ohio","coordinates":[-83.12754,41.11999]}, {"dem":4215,"rep":18950,"total":23956,"name":"Walker, Georgia","coordinates":[-85.30545,34.7358]}, {"dem":8764,"rep":14543,"total":23938,"name":"Beaufort, North Carolina","coordinates":[-76.84201,35.48231]}, {"dem":6809,"rep":15494,"total":23908,"name":"Tehama, California","coordinates":[-122.23227,40.12615]}, {"dem":9015,"rep":12920,"total":23880,"name":"Itasca, Minnesota","coordinates":[-93.6111,47.49081]}, {"dem":10717,"rep":11819,"total":23865,"name":"Franklin, Kentucky","coordinates":[-84.86878,38.23491]}, {"dem":6146,"rep":16005,"total":23762,"name":"Lyon, Nevada","coordinates":[-119.19742,39.02221]}, {"dem":7526,"rep":14884,"total":23757,"name":"St. Joseph, Michigan","coordinates":[-85.52287,41.91148]}, {"dem":4243,"rep":18590,"total":23740,"name":"Shelby, Ohio","coordinates":[-84.20414,40.33668]}, {"dem":9063,"rep":14272,"total":23732,"name":"Columbus, North Carolina","coordinates":[-78.6393,34.2616]}, {"dem":8886,"rep":13206,"total":23720,"name":"Franklin, Washington","coordinates":[-118.90694,46.53457]}, {"dem":3645,"rep":19552,"total":23637,"name":"Bedford, Pennsylvania","coordinates":[-78.49474,39.99863]}, {"dem":3980,"rep":18658,"total":23627,"name":"Auglaize, Ohio","coordinates":[-84.22401,40.5613]}, {"dem":4216,"rep":18562,"total":23583,"name":"Greene, Tennessee","coordinates":[-82.84752,36.17948]}, {"dem":4373,"rep":18276,"total":23515,"name":"Taney, Missouri","coordinates":[-93.04281,36.64982]}, {"dem":5785,"rep":16910,"total":23481,"name":"Tipton, Tennessee","coordinates":[-89.7668,35.50025]}, {"dem":4853,"rep":17874,"total":23458,"name":"Effingham, Georgia","coordinates":[-81.34337,32.36168]}, {"dem":4919,"rep":17610,"total":23391,"name":"Loudon, Tennessee","coordinates":[-84.31408,35.73508]}, {"dem":6309,"rep":16021,"total":23348,"name":"Venango, Pennsylvania","coordinates":[-79.76581,41.40071]}, {"dem":6144,"rep":15474,"total":23326,"name":"Jessamine, Kentucky","coordinates":[-84.58396,37.87329]}, {"dem":4681,"rep":17727,"total":23297,"name":"Kerr, Texas","coordinates":[-99.35333,30.05995]}, {"dem":8065,"rep":13454,"total":23237,"name":"Grundy, Illinois","coordinates":[-88.40105,41.2924]}, {"dem":12443,"rep":9148,"total":23147,"name":"Knox, Maine","coordinates":[-69.03851,44.04204]}, {"dem":7944,"rep":13511,"total":23136,"name":"Calaveras, California","coordinates":[-120.56144,38.18389]}, {"dem":10095,"rep":11276,"total":23067,"name":"Clinton, Iowa","coordinates":[-90.53424,41.89807]}, {"dem":6964,"rep":14668,"total":23029,"name":"Marion, West Virginia","coordinates":[-80.2434,39.50583]}, {"dem":8986,"rep":12282,"total":23001,"name":"Boone, Illinois","coordinates":[-88.82429,42.31898]}, {"dem":7910,"rep":13170,"total":22998,"name":"Yuba, California","coordinates":[-121.34425,39.27013]}, {"dem":4704,"rep":17404,"total":22982,"name":"Mercer, West Virginia","coordinates":[-81.10645,37.40344]}, {"dem":9862,"rep":11621,"total":22965,"name":"Cerro Gordo, Iowa","coordinates":[-93.25096,43.07497]}, {"dem":8050,"rep":14359,"total":22877,"name":"St. Mary, Louisiana","coordinates":[-91.4638,29.62934]}, {"dem":2780,"rep":19606,"total":22780,"name":"Hardin, Texas","coordinates":[-94.39317,30.32964]}, {"dem":7570,"rep":13815,"total":22749,"name":"Polk, Wisconsin","coordinates":[-92.44706,45.46204]}, {"dem":10440,"rep":10378,"total":22707,"name":"Waldo, Maine","coordinates":[-69.13895,44.50583]}, {"dem":10210,"rep":10796,"total":22683,"name":"Sullivan, New Hampshire","coordinates":[-72.22208,43.36118]}, {"dem":5767,"rep":15161,"total":22677,"name":"Stevens, Washington","coordinates":[-117.85445,48.38872]}, {"dem":7879,"rep":13606,"total":22643,"name":"Barron, Wisconsin","coordinates":[-91.85289,45.43719]}, {"dem":6212,"rep":15173,"total":22640,"name":"Newaygo, Michigan","coordinates":[-85.79137,43.56271]}, {"dem":14340,"rep":5454,"total":22635,"name":"Windham, Vermont","coordinates":[-72.72195,42.99533]}, {"dem":6846,"rep":14771,"total":22622,"name":"Nacogdoches, Texas","coordinates":[-94.62024,31.62055]}, {"dem":7270,"rep":14243,"total":22595,"name":"Cass, Michigan","coordinates":[-86.00014,41.91724]}, {"dem":5000,"rep":16256,"total":22569,"name":"Pope, Arkansas","coordinates":[-93.02681,35.45655]}, {"dem":6223,"rep":14810,"total":22556,"name":"Ravalli, Montana","coordinates":[-114.10579,46.07774]}, {"dem":4665,"rep":17116,"total":22550,"name":"Stokes, North Carolina","coordinates":[-80.26621,36.3935]}, {"dem":4768,"rep":16944,"total":22514,"name":"Camden, Missouri","coordinates":[-92.76532,38.02652]}, {"dem":11345,"rep":9659,"total":22511,"name":"Douglas, Wisconsin","coordinates":[-91.89247,46.46321]}, {"dem":17901,"rep":2960,"total":22472,"name":"Charlottesville, Virginia","coordinates":[-78.48538,38.03765]}, {"dem":4488,"rep":16686,"total":22450,"name":"Crawford, Arkansas","coordinates":[-94.23621,35.58301]}, {"dem":6689,"rep":14322,"total":22360,"name":"Macoupin, Illinois","coordinates":[-89.92633,39.26591]}, {"dem":7003,"rep":14182,"total":22312,"name":"Gila, Arizona","coordinates":[-110.81186,33.78961]}, {"dem":7526,"rep":13260,"total":22299,"name":"Tioga, New York","coordinates":[-76.29745,42.17805]}, {"dem":3882,"rep":17316,"total":22286,"name":"Grady, Oklahoma","coordinates":[-97.88689,35.02105]}, {"dem":10083,"rep":10737,"total":22243,"name":"Knox, Illinois","coordinates":[-90.21379,40.93094]}, {"dem":5048,"rep":15825,"total":22224,"name":"Washington, Oklahoma","coordinates":[-95.90615,36.70438]}, {"dem":8285,"rep":12653,"total":22218,"name":"Ottawa, Ohio","coordinates":[-83.01261,41.54549]}, {"dem":7759,"rep":13349,"total":22218,"name":"Culpeper, Virginia","coordinates":[-77.95647,38.48593]}, {"dem":15020,"rep":6728,"total":22113,"name":"Gadsden, Florida","coordinates":[-84.6126,30.57868]}, {"dem":9026,"rep":11488,"total":22091,"name":"Dunn, Wisconsin","coordinates":[-91.89764,44.94775]}, {"dem":7188,"rep":14108,"total":22083,"name":"Christian, Kentucky","coordinates":[-87.49298,36.89205]}, {"dem":6317,"rep":13828,"total":22064,"name":"Saline, Kansas","coordinates":[-97.65147,38.7918]}, {"dem":6282,"rep":14408,"total":22060,"name":"Hall, Nebraska","coordinates":[-98.50266,40.86602]}, {"dem":7405,"rep":13073,"total":22050,"name":"Greene, New York","coordinates":[-74.14202,42.27982]}, {"dem":5297,"rep":15122,"total":21973,"name":"Fremont, Colorado","coordinates":[-105.42495,38.45516]}, {"dem":12521,"rep":7841,"total":21924,"name":"San Benito, California","coordinates":[-121.08581,36.61165]}, {"dem":2799,"rep":18473,"total":21890,"name":"Van Zandt, Texas","coordinates":[-95.8369,32.55878]}, {"dem":3604,"rep":17782,"total":21883,"name":"Pearl River, Mississippi","coordinates":[-89.5869,30.77479]}, {"dem":7309,"rep":13003,"total":21863,"name":"Coles, Illinois","coordinates":[-88.22078,39.51367]}, {"dem":4573,"rep":11169,"total":21829,"name":"Tooele, Utah","coordinates":[-113.12397,40.46775]}, {"dem":6227,"rep":13966,"total":21785,"name":"Douglas, Minnesota","coordinates":[-95.46215,45.93682]}, {"dem":7266,"rep":12785,"total":21772,"name":"Kandiyohi, Minnesota","coordinates":[-95.00498,45.15271]}, {"dem":6092,"rep":15167,"total":21759,"name":"Cherokee, South Carolina","coordinates":[-81.60764,35.04979]}, {"dem":5270,"rep":15602,"total":21756,"name":"Davie, North Carolina","coordinates":[-80.54255,35.92935]}, {"dem":3384,"rep":17506,"total":21726,"name":"Mercer, Ohio","coordinates":[-84.63205,40.53533]}, {"dem":4397,"rep":16009,"total":21710,"name":"Garfield, Oklahoma","coordinates":[-97.78845,36.37805]}, {"dem":13576,"rep":5104,"total":21703,"name":"McKinley, New Mexico","coordinates":[-108.25326,35.58387]}, {"dem":4837,"rep":15880,"total":21669,"name":"Roane, Tennessee","coordinates":[-84.52392,35.84725]}, {"dem":7871,"rep":13030,"total":21656,"name":"San Patricio, Texas","coordinates":[-97.51715,28.01179]}, {"dem":10664,"rep":9304,"total":21616,"name":"Sagadahoc, Maine","coordinates":[-69.84422,43.91684]}, {"dem":4647,"rep":15957,"total":21571,"name":"Logan, Ohio","coordinates":[-83.76634,40.38755]}, {"dem":8688,"rep":10783,"total":21564,"name":"Beltrami, Minnesota","coordinates":[-95.00505,47.8795]}, {"dem":9341,"rep":10107,"total":21532,"name":"Riley, Kansas","coordinates":[-96.72748,39.29121]}, {"dem":10241,"rep":9727,"total":21503,"name":"Lincoln, Maine","coordinates":[-69.51362,43.99478]}, {"dem":8104,"rep":12117,"total":21473,"name":"Oneida, Wisconsin","coordinates":[-89.53453,45.71617]}, {"dem":9351,"rep":8752,"total":21411,"name":"Franklin, Vermont","coordinates":[-72.9094,44.85896]}, {"dem":6069,"rep":13709,"total":21225,"name":"Fulton, Ohio","coordinates":[-84.12426,41.59726]}, {"dem":6496,"rep":13462,"total":21214,"name":"Fulton, New York","coordinates":[-74.42367,43.1156]}, {"dem":8382,"rep":11258,"total":21189,"name":"Pierce, Wisconsin","coordinates":[-92.42627,44.72533]}, {"dem":5466,"rep":14382,"total":21186,"name":"Montrose, Colorado","coordinates":[-108.26628,38.4075]}, {"dem":4632,"rep":15616,"total":21158,"name":"Perry, Pennsylvania","coordinates":[-77.26632,40.39777]}, {"dem":5930,"rep":13719,"total":21132,"name":"Johnson, Missouri","coordinates":[-93.81186,38.74152]}, {"dem":4763,"rep":14569,"total":21129,"name":"Buffalo, Nebraska","coordinates":[-99.07498,40.85522]}, {"dem":3453,"rep":16898,"total":21084,"name":"Carter, Tennessee","coordinates":[-82.12659,36.28474]}, {"dem":7881,"rep":12204,"total":21075,"name":"Isle of Wight, Virginia","coordinates":[-76.70756,36.90141]}, {"dem":6397,"rep":14257,"total":21041,"name":"Jackson, Florida","coordinates":[-85.20881,30.78924]}, {"dem":5657,"rep":13635,"total":21016,"name":"Isanti, Minnesota","coordinates":[-93.29633,45.56243]}, {"dem":3673,"rep":16672,"total":20984,"name":"Jackson, Alabama","coordinates":[-85.98005,34.76411]}, {"dem":5819,"rep":13343,"total":20943,"name":"Bonner, Idaho","coordinates":[-116.61236,48.31679]}, {"dem":8283,"rep":12217,"total":20856,"name":"Duplin, North Carolina","coordinates":[-77.93354,34.9344]}, {"dem":6434,"rep":13431,"total":20802,"name":"Nelson, Kentucky","coordinates":[-85.46593,37.80311]}, {"dem":3507,"rep":16648,"total":20774,"name":"Hawkins, Tennessee","coordinates":[-82.93148,36.45208]}, {"dem":4221,"rep":15875,"total":20767,"name":"Coffee, Alabama","coordinates":[-85.9896,31.40225]}, {"dem":12661,"rep":7569,"total":20743,"name":"St. John the Baptist, Louisiana","coordinates":[-90.49095,30.14406]}, {"dem":4075,"rep":15857,"total":20692,"name":"Hamblen, Tennessee","coordinates":[-83.26607,36.21839]}, {"dem":10503,"rep":7333,"total":20641,"name":"Summit, Utah","coordinates":[-110.96848,40.87206]}, {"dem":6276,"rep":13196,"total":20580,"name":"Shelby, Kentucky","coordinates":[-85.22824,38.23901]}, {"dem":4325,"rep":15446,"total":20565,"name":"Preble, Ohio","coordinates":[-84.64475,39.73881]}, {"dem":8653,"rep":10724,"total":20553,"name":"Talbot, Maryland","coordinates":[-76.17847,38.74834]}, {"dem":5273,"rep":14094,"total":20513,"name":"Shenandoah, Virginia","coordinates":[-78.57398,38.8562]}, {"dem":7234,"rep":11341,"total":20492,"name":"Siskiyou, California","coordinates":[-122.53328,41.58798]}, {"dem":6021,"rep":13591,"total":20454,"name":"Boyd, Kentucky","coordinates":[-82.6814,38.36]}, {"dem":4310,"rep":15277,"total":20345,"name":"Hopkins, Kentucky","coordinates":[-87.54219,37.31107]}, {"dem":7768,"rep":11083,"total":20343,"name":"Stephenson, Illinois","coordinates":[-89.66599,42.34972]}, {"dem":12656,"rep":6037,"total":20276,"name":"Jefferson, Washington","coordinates":[-123.52705,47.8057]}, {"dem":5534,"rep":12872,"total":20271,"name":"Chaves, New Mexico","coordinates":[-104.46983,33.3616]}, {"dem":8771,"rep":9900,"total":20244,"name":"Cortland, New York","coordinates":[-76.07623,42.59403]}, {"dem":6775,"rep":11921,"total":20160,"name":"Chenango, New York","coordinates":[-75.60224,42.47802]}, {"dem":5124,"rep":13895,"total":20155,"name":"Henry, Indiana","coordinates":[-85.39736,39.92959]}, {"dem":5581,"rep":13425,"total":20149,"name":"Oconee, Georgia","coordinates":[-83.43772,33.83412]}, {"dem":3643,"rep":15700,"total":20120,"name":"Kendall, Texas","coordinates":[-98.70926,29.94352]}, {"dem":6124,"rep":11887,"total":20060,"name":"Otero, New Mexico","coordinates":[-105.7513,32.61559]}, {"dem":5640,"rep":12872,"total":20058,"name":"Benton, Minnesota","coordinates":[-94.00143,45.70122]}, {"dem":6243,"rep":12995,"total":20046,"name":"Marinette, Wisconsin","coordinates":[-87.99119,45.34689]}, {"dem":5389,"rep":13365,"total":19984,"name":"Dubois, Indiana","coordinates":[-86.87338,38.37334]}, {"dem":5884,"rep":13253,"total":19978,"name":"Oconto, Wisconsin","coordinates":[-88.20651,44.99657]}, {"dem":12229,"rep":7332,"total":19977,"name":"Vance, North Carolina","coordinates":[-78.40543,36.36548]}, {"dem":4743,"rep":14417,"total":19971,"name":"Coffee, Tennessee","coordinates":[-86.0782,35.48876]}, {"dem":4799,"rep":14095,"total":19940,"name":"Hillsdale, Michigan","coordinates":[-84.63747,41.92746]}, {"dem":4667,"rep":14568,"total":19875,"name":"McDowell, North Carolina","coordinates":[-82.04804,35.68227]}, {"dem":5092,"rep":13207,"total":19864,"name":"Woodford, Illinois","coordinates":[-89.21058,40.78978]}, {"dem":4187,"rep":15176,"total":19852,"name":"Polk, Texas","coordinates":[-94.83733,30.78455]}, {"dem":6091,"rep":12884,"total":19796,"name":"Walker, Texas","coordinates":[-95.56982,30.74316]}, {"dem":6627,"rep":11942,"total":19792,"name":"Delaware, New York","coordinates":[-74.96672,42.19398]}, {"dem":4169,"rep":14682,"total":19766,"name":"Baxter, Arkansas","coordinates":[-92.32994,36.28026]}, {"dem":6056,"rep":12742,"total":19751,"name":"Shawano, Wisconsin","coordinates":[-88.75581,44.78964]}, {"dem":2282,"rep":12230,"total":19735,"name":"Box Elder, Utah","coordinates":[-113.12622,41.27606]}, {"dem":6707,"rep":12159,"total":19710,"name":"Henderson, Kentucky","coordinates":[-87.57257,37.79254]}, {"dem":4539,"rep":14494,"total":19706,"name":"Huntingdon, Pennsylvania","coordinates":[-77.96859,40.42231]}, {"dem":7048,"rep":11352,"total":19670,"name":"Monroe, Wisconsin","coordinates":[-90.61996,43.94517]}, {"dem":5033,"rep":13147,"total":19667,"name":"Eddy, New Mexico","coordinates":[-104.30643,32.45783]}, {"dem":9252,"rep":8138,"total":19664,"name":"Clatsop, Oregon","coordinates":[-123.70503,46.0245]}, {"dem":7969,"rep":10872,"total":19643,"name":"Lafayette, Mississippi","coordinates":[-89.48538,34.35307]}, {"dem":5404,"rep":13096,"total":19619,"name":"Gloucester, Virginia","coordinates":[-76.5235,37.40354]}, {"dem":7833,"rep":11185,"total":19615,"name":"Person, North Carolina","coordinates":[-78.96562,36.38635]}, {"dem":7222,"rep":11460,"total":19609,"name":"Dare, North Carolina","coordinates":[-75.76753,35.60626]}, {"dem":4353,"rep":14573,"total":19607,"name":"Brown, Ohio","coordinates":[-83.86677,38.93137]}, {"dem":5094,"rep":13324,"total":19595,"name":"Nye, Nevada","coordinates":[-116.45901,37.96586]}, {"dem":5258,"rep":13786,"total":19547,"name":"Gibson, Tennessee","coordinates":[-88.93381,35.99163]}, {"dem":6752,"rep":12411,"total":19530,"name":"Laurens, Georgia","coordinates":[-82.92631,32.39321]}, {"dem":5519,"rep":13594,"total":19486,"name":"Tallapoosa, Alabama","coordinates":[-85.79961,32.8633]}, {"dem":3650,"rep":15192,"total":19478,"name":"Jefferson, Pennsylvania","coordinates":[-79.01241,41.13802]}, {"dem":8368,"rep":9584,"total":19434,"name":"Muscatine, Iowa","coordinates":[-91.11869,41.48377]}, {"dem":4790,"rep":13998,"total":19432,"name":"Wilson, Texas","coordinates":[-98.08673,29.17388]}, {"dem":9284,"rep":9767,"total":19416,"name":"Warren, Mississippi","coordinates":[-90.85238,32.35609]}, {"dem":5101,"rep":13775,"total":19395,"name":"Levy, Florida","coordinates":[-82.78346,29.28445]}, {"dem":5874,"rep":13055,"total":19394,"name":"Fayette, Tennessee","coordinates":[-89.4138,35.19699]}, {"dem":5535,"rep":12629,"total":19354,"name":"Monroe, Illinois","coordinates":[-90.17907,38.27798]}, {"dem":8501,"rep":10383,"total":19328,"name":"Richmond, North Carolina","coordinates":[-79.75569,35.00463]}, {"dem":9579,"rep":9210,"total":19256,"name":"Russell, Alabama","coordinates":[-85.18697,32.28981]}, {"dem":4873,"rep":13446,"total":19249,"name":"Sanilac, Michigan","coordinates":[-82.64281,43.44915]}, {"dem":4625,"rep":13611,"total":19237,"name":"Crawford, Ohio","coordinates":[-82.92478,40.84852]}, {"dem":3797,"rep":14638,"total":19204,"name":"Burnet, Texas","coordinates":[-98.20118,30.78963]}, {"dem":4989,"rep":13057,"total":19193,"name":"Callaway, Missouri","coordinates":[-91.92344,38.83554]}, {"dem":6241,"rep":11198,"total":19179,"name":"Steele, Minnesota","coordinates":[-93.22045,44.01526]}, {"dem":4210,"rep":14035,"total":19152,"name":"Lawrence, Indiana","coordinates":[-86.48781,38.83981]}, {"dem":8212,"rep":9529,"total":19103,"name":"Des Moines, Iowa","coordinates":[-91.18692,40.91533]}, {"dem":3494,"rep":14776,"total":19072,"name":"Jefferson, Tennessee","coordinates":[-83.44114,36.04833]}, {"dem":6595,"rep":11301,"total":19054,"name":"Montgomery, New York","coordinates":[-74.43535,42.90089]}, {"dem":7109,"rep":10560,"total":19034,"name":"Jasper, Iowa","coordinates":[-93.05414,41.68555]}, {"dem":11219,"rep":5297,"total":19031,"name":"Addison, Vermont","coordinates":[-73.14158,44.03124]}, {"dem":3935,"rep":14675,"total":18994,"name":"Rusk, Texas","coordinates":[-94.75638,32.10942]}, {"dem":9122,"rep":8693,"total":18985,"name":"Green, Wisconsin","coordinates":[-89.60507,42.67552]}, {"dem":4248,"rep":13633,"total":18979,"name":"Logan, Oklahoma","coordinates":[-97.45076,35.91415]}, {"dem":5597,"rep":12577,"total":18966,"name":"Osage, Oklahoma","coordinates":[-96.40811,36.62429]}, {"dem":3181,"rep":15191,"total":18959,"name":"Gordon, Georgia","coordinates":[-84.87386,34.50966]}, {"dem":7489,"rep":10100,"total":18955,"name":"Kittitas, Washington","coordinates":[-120.6767,47.12444]}, {"dem":11059,"rep":7303,"total":18952,"name":"Danville, Virginia","coordinates":[-79.40807,36.58333]}, {"dem":5930,"rep":12310,"total":18901,"name":"Camden, Georgia","coordinates":[-81.64201,30.91335]}, {"dem":5123,"rep":12891,"total":18863,"name":"Susquehanna, Pennsylvania","coordinates":[-75.80096,41.81966]}, {"dem":4978,"rep":12155,"total":18807,"name":"McLeod, Minnesota","coordinates":[-94.27232,44.82165]}, {"dem":7142,"rep":11228,"total":18802,"name":"Thomas, Georgia","coordinates":[-83.91981,30.86461]}, {"dem":6972,"rep":10616,"total":18802,"name":"Emmet, Michigan","coordinates":[-84.98682,45.59009]}, {"dem":12836,"rep":5789,"total":18792,"name":"Dallas, Alabama","coordinates":[-87.11435,32.33353]}, {"dem":2922,"rep":14961,"total":18767,"name":"Putnam, Ohio","coordinates":[-84.12987,41.02453]}, {"dem":3510,"rep":14691,"total":18755,"name":"McMinn, Tennessee","coordinates":[-84.61994,35.42447]}, {"dem":4413,"rep":13808,"total":18749,"name":"Dale, Alabama","coordinates":[-85.60947,31.43065]}, {"dem":4494,"rep":13375,"total":18739,"name":"Botetourt, Virginia","coordinates":[-79.79754,37.56548]}, {"dem":2630,"rep":15700,"total":18727,"name":"Wood, Texas","coordinates":[-95.38216,32.78358]}, {"dem":7713,"rep":9870,"total":18713,"name":"Jackson, North Carolina","coordinates":[-83.11996,35.28105]}, {"dem":4727,"rep":13116,"total":18711,"name":"Franklin, Illinois","coordinates":[-88.92632,37.99185]}, {"dem":4722,"rep":13233,"total":18699,"name":"Dickson, Tennessee","coordinates":[-87.36415,36.14553]}, {"dem":3964,"rep":14287,"total":18694,"name":"Suwannee, Florida","coordinates":[-82.99275,30.18924]}, {"dem":4882,"rep":12525,"total":18692,"name":"Allegany, New York","coordinates":[-78.02615,42.24785]}, {"dem":4066,"rep":13838,"total":18675,"name":"Clinton, Ohio","coordinates":[-83.79568,39.43022]}, {"dem":7107,"rep":10761,"total":18669,"name":"Lincoln, Louisiana","coordinates":[-92.6623,32.60182]}, {"dem":5692,"rep":12556,"total":18628,"name":"Washington, Louisiana","coordinates":[-90.04625,30.85214]}, {"dem":3583,"rep":14561,"total":18611,"name":"Lamar, Texas","coordinates":[-95.57034,33.66726]}, {"dem":3877,"rep":14094,"total":18601,"name":"Mifflin, Pennsylvania","coordinates":[-77.65183,40.60161]}, {"dem":2895,"rep":15168,"total":18566,"name":"Tazewell, Virginia","coordinates":[-81.56292,37.12539]}, {"dem":3401,"rep":13551,"total":18559,"name":"Elko, Nevada","coordinates":[-115.35142,41.14113]}, {"dem":4783,"rep":12943,"total":18558,"name":"Harrison, Indiana","coordinates":[-86.10376,38.18645]}, {"dem":4766,"rep":12709,"total":18553,"name":"Phelps, Missouri","coordinates":[-91.79034,37.86632]}, {"dem":4002,"rep":13752,"total":18534,"name":"Carter, Oklahoma","coordinates":[-97.28792,34.25184]}, {"dem":3773,"rep":14020,"total":18501,"name":"Highland, Ohio","coordinates":[-83.60135,39.18442]}, {"dem":6436,"rep":11121,"total":18492,"name":"Delta, Michigan","coordinates":[-86.90193,45.80522]}, {"dem":4275,"rep":13483,"total":18488,"name":"Barren, Kentucky","coordinates":[-85.9321,36.9628]}, {"dem":5145,"rep":12477,"total":18434,"name":"Warren, Pennsylvania","coordinates":[-79.29818,41.83429]}, {"dem":2911,"rep":15081,"total":18369,"name":"Chilton, Alabama","coordinates":[-86.7266,32.85405]}, {"dem":3901,"rep":13614,"total":18325,"name":"Tioga, Pennsylvania","coordinates":[-77.25728,41.76685]}, {"dem":3767,"rep":13893,"total":18271,"name":"Alexander, North Carolina","coordinates":[-81.17746,35.92095]}, {"dem":5064,"rep":12225,"total":18253,"name":"Coryell, Texas","coordinates":[-97.79802,31.39117]}, {"dem":9726,"rep":7760,"total":18230,"name":"Hoke, North Carolina","coordinates":[-79.24196,35.01723]}, {"dem":8460,"rep":8160,"total":18211,"name":"Carlton, Minnesota","coordinates":[-92.67104,46.60381]}, {"dem":1324,"rep":15778,"total":18199,"name":"Campbell, Wyoming","coordinates":[-105.51701,44.19199]}, {"dem":2300,"rep":14785,"total":18194,"name":"Sioux, Iowa","coordinates":[-96.178,43.08264]}, {"dem":5368,"rep":11688,"total":18192,"name":"Defiance, Ohio","coordinates":[-84.48643,41.32167]}, {"dem":8093,"rep":7265,"total":18173,"name":"Latah, Idaho","coordinates":[-116.73097,46.81892]}, {"dem":6260,"rep":11542,"total":18145,"name":"Webster, Louisiana","coordinates":[-93.33982,32.73215]}, {"dem":8859,"rep":8576,"total":18124,"name":"Oktibbeha, Mississippi","coordinates":[-88.87615,33.42231]}, {"dem":4324,"rep":12810,"total":18111,"name":"Pettis, Missouri","coordinates":[-93.2852,38.72736]}, {"dem":4594,"rep":12631,"total":18104,"name":"Champaign, Ohio","coordinates":[-83.7676,40.13277]}, {"dem":7886,"rep":8437,"total":18097,"name":"Nicollet, Minnesota","coordinates":[-94.24568,44.35882]}, {"dem":4798,"rep":12288,"total":18082,"name":"Marshall, Indiana","coordinates":[-86.26903,41.325]}, {"dem":4247,"rep":12718,"total":17994,"name":"Shelby, Indiana","coordinates":[-85.79217,39.52413]}, {"dem":10212,"rep":6262,"total":17993,"name":"Harrisonburg, Virginia","coordinates":[-78.8733,38.43625]}, {"dem":7652,"rep":9146,"total":17980,"name":"Marshall, Iowa","coordinates":[-92.98145,42.04169]}, {"dem":5169,"rep":11773,"total":17960,"name":"Warren, Virginia","coordinates":[-78.20759,38.90822]}, {"dem":5493,"rep":11139,"total":17938,"name":"Ohio, West Virginia","coordinates":[-80.62072,40.09893]}, {"dem":3086,"rep":14182,"total":17904,"name":"Stephens, Oklahoma","coordinates":[-97.8556,34.48136]}, {"dem":6558,"rep":10520,"total":17869,"name":"Transylvania, North Carolina","coordinates":[-82.81666,35.2101]}, {"dem":5482,"rep":10962,"total":17816,"name":"Marion, Iowa","coordinates":[-93.09384,41.33145]}, {"dem":6004,"rep":10485,"total":17734,"name":"Amador, California","coordinates":[-120.65385,38.44355]}, {"dem":4876,"rep":12127,"total":17734,"name":"Macon, North Carolina","coordinates":[-83.4219,35.15295]}, {"dem":7437,"rep":8823,"total":17715,"name":"Mower, Minnesota","coordinates":[-92.75951,43.66624]}, {"dem":3930,"rep":12495,"total":17712,"name":"Lea, New Mexico","coordinates":[-103.41327,32.79568]}, {"dem":5061,"rep":11786,"total":17663,"name":"Branch, Michigan","coordinates":[-85.06688,41.91845]}, {"dem":2450,"rep":11561,"total":17654,"name":"Iron, Utah","coordinates":[-113.30674,37.9093]}, {"dem":3344,"rep":13811,"total":17637,"name":"Hancock, Mississippi","coordinates":[-89.48279,30.39164]}, {"dem":6212,"rep":10528,"total":17631,"name":"Louisa, Virginia","coordinates":[-77.95979,37.9727]}, {"dem":3160,"rep":13880,"total":17624,"name":"Yadkin, North Carolina","coordinates":[-80.66516,36.15876]}, {"dem":3637,"rep":12925,"total":17614,"name":"Morrison, Minnesota","coordinates":[-94.26661,46.02048]}, {"dem":3083,"rep":13635,"total":17609,"name":"Effingham, Illinois","coordinates":[-88.59284,39.04794]}, {"dem":8026,"rep":8584,"total":17608,"name":"Door, Wisconsin","coordinates":[-87.04868,45.09341]}, {"dem":3843,"rep":12859,"total":17573,"name":"Jackson, Indiana","coordinates":[-86.04251,38.91195]}, {"dem":4273,"rep":12576,"total":17535,"name":"Clarion, Pennsylvania","coordinates":[-79.42036,41.19815]}, {"dem":6180,"rep":10622,"total":17468,"name":"Union, Pennsylvania","coordinates":[-77.05547,40.96217]}, {"dem":2881,"rep":13893,"total":17455,"name":"Howell, Missouri","coordinates":[-91.88736,36.77436]}, {"dem":6305,"rep":10056,"total":17430,"name":"Webster, Iowa","coordinates":[-94.17583,42.43357]}, {"dem":3945,"rep":12412,"total":17419,"name":"Clinton, Illinois","coordinates":[-89.42622,38.60629]}, {"dem":8615,"rep":8180,"total":17391,"name":"Pasquotank, North Carolina","coordinates":[-76.26069,36.26519]}, {"dem":9539,"rep":5925,"total":17381,"name":"Bennington, Vermont","coordinates":[-73.11146,43.03532]}, {"dem":4358,"rep":11939,"total":17308,"name":"Williams, Ohio","coordinates":[-84.58432,41.56495]}, {"dem":8146,"rep":7403,"total":17305,"name":"Whitman, Washington","coordinates":[-117.53538,46.90594]}, {"dem":3904,"rep":12442,"total":17298,"name":"Wyoming, New York","coordinates":[-78.22856,42.70136]}, {"dem":4779,"rep":11631,"total":17290,"name":"Madison, Ohio","coordinates":[-83.40088,39.8966]}, {"dem":3711,"rep":12753,"total":17271,"name":"Pittsburg, Oklahoma","coordinates":[-95.74813,34.92554]}, {"dem":5957,"rep":10521,"total":17270,"name":"Orange, Virginia","coordinates":[-78.00962,38.25019]}, {"dem":3036,"rep":13650,"total":17259,"name":"Butler, Missouri","coordinates":[-90.40313,36.71518]}, {"dem":3575,"rep":13168,"total":17256,"name":"Scott, Missouri","coordinates":[-89.56809,37.04779]}, {"dem":7627,"rep":9091,"total":17251,"name":"Colleton, South Carolina","coordinates":[-80.65524,32.83501]}, {"dem":4634,"rep":12085,"total":17246,"name":"Medina, Texas","coordinates":[-99.11108,29.35366]}, {"dem":5208,"rep":10880,"total":17222,"name":"Becker, Minnesota","coordinates":[-95.74175,46.93762]}, {"dem":3250,"rep":13362,"total":17221,"name":"Le Flore, Oklahoma","coordinates":[-94.69507,34.89735]}, {"dem":7762,"rep":7958,"total":17218,"name":"Essex, New York","coordinates":[-73.77843,44.1096]}, {"dem":4828,"rep":10699,"total":17201,"name":"Nez Perce, Idaho","coordinates":[-116.7609,46.33379]}, {"dem":5827,"rep":10305,"total":17168,"name":"Mecosta, Michigan","coordinates":[-85.33275,43.63529]}, {"dem":3231,"rep":12154,"total":17130,"name":"Sweetwater, Wyoming","coordinates":[-108.87567,41.66032]}, {"dem":3186,"rep":13374,"total":17093,"name":"Monroe, Tennessee","coordinates":[-84.2497,35.44781]}, {"dem":6298,"rep":9610,"total":17091,"name":"Okanogan, Washington","coordinates":[-119.74223,48.54845]}, {"dem":4369,"rep":11859,"total":17074,"name":"Marion, Illinois","coordinates":[-88.92036,38.64823]}, {"dem":6890,"rep":7602,"total":17060,"name":"Albany, Wyoming","coordinates":[-105.72188,41.66551]}, {"dem":4200,"rep":11167,"total":17023,"name":"Fremont, Wyoming","coordinates":[-108.60893,43.05483]}, {"dem":6897,"rep":9704,"total":17001,"name":"Halifax, Virginia","coordinates":[-78.93961,36.76646]}, {"dem":4425,"rep":11695,"total":16999,"name":"Jefferson, Illinois","coordinates":[-88.92421,38.30077]}, {"dem":3369,"rep":13201,"total":16977,"name":"Anderson, Texas","coordinates":[-95.66172,31.84126]}, {"dem":7297,"rep":8221,"total":16952,"name":"Franklin, New York","coordinates":[-74.31067,44.59437]}, {"dem":3942,"rep":12054,"total":16902,"name":"DeKalb, Indiana","coordinates":[-85.00018,41.40118]}, {"dem":4060,"rep":11885,"total":16900,"name":"Powhatan, Virginia","coordinates":[-77.91285,37.5494]}, {"dem":5855,"rep":10456,"total":16894,"name":"Union, Arkansas","coordinates":[-92.59814,33.16821]}, {"dem":3904,"rep":12198,"total":16890,"name":"Noble, Indiana","coordinates":[-85.41727,41.40467]}, {"dem":2894,"rep":13169,"total":16858,"name":"McClain, Oklahoma","coordinates":[-97.4498,35.01643]}, {"dem":11380,"rep":5244,"total":16825,"name":"Washington, Mississippi","coordinates":[-90.94444,33.27317]}, {"dem":6217,"rep":10017,"total":16807,"name":"Newberry, South Carolina","coordinates":[-81.59967,34.28988]}, {"dem":3738,"rep":12172,"total":16803,"name":"Kay, Oklahoma","coordinates":[-97.14386,36.81488]}, {"dem":4087,"rep":11655,"total":16790,"name":"Delta, Colorado","coordinates":[-107.86489,38.86159]}, {"dem":3469,"rep":12919,"total":16790,"name":"Cherokee, Texas","coordinates":[-95.15634,31.84388]}, {"dem":2948,"rep":13339,"total":16786,"name":"Chambers, Texas","coordinates":[-94.66944,29.69637]}, {"dem":5748,"rep":10531,"total":16784,"name":"Waller, Texas","coordinates":[-95.98214,30.01359]}, {"dem":3177,"rep":12840,"total":16743,"name":"Webster, Missouri","coordinates":[-92.87607,37.2808]}, {"dem":2901,"rep":13089,"total":16715,"name":"Lawrence, Missouri","coordinates":[-93.83055,37.10658]}, {"dem":3672,"rep":12322,"total":16698,"name":"Marshall, Kentucky","coordinates":[-88.33275,36.88201]}, {"dem":2665,"rep":13471,"total":16633,"name":"Vernon, Louisiana","coordinates":[-93.18152,31.11056]}, {"dem":2924,"rep":10907,"total":16625,"name":"Bingham, Idaho","coordinates":[-112.3992,43.21635]}, {"dem":7144,"rep":8968,"total":16621,"name":"Natchitoches, Louisiana","coordinates":[-93.08261,31.73255]}, {"dem":3308,"rep":12671,"total":16606,"name":"Graves, Kentucky","coordinates":[-88.64989,36.72334]}, {"dem":5035,"rep":11165,"total":16586,"name":"Avoyelles, Louisiana","coordinates":[-91.98327,31.0885]}, {"dem":6858,"rep":9312,"total":16581,"name":"Chesterfield, South Carolina","coordinates":[-80.15922,34.63701]}, {"dem":6029,"rep":9281,"total":16571,"name":"Bureau, Illinois","coordinates":[-89.52837,41.4013]}, {"dem":2887,"rep":13158,"total":16567,"name":"Stone, Missouri","coordinates":[-93.4737,36.751]}, {"dem":4359,"rep":11445,"total":16557,"name":"Guernsey, Ohio","coordinates":[-81.49787,40.05666]}, {"dem":3761,"rep":11948,"total":16548,"name":"Morrow, Ohio","coordinates":[-82.79772,40.52526]}, {"dem":4015,"rep":11993,"total":16540,"name":"Floyd, Kentucky","coordinates":[-82.73972,37.55245]}, {"dem":4086,"rep":11936,"total":16502,"name":"Harris, Georgia","coordinates":[-84.91243,32.73154]}, {"dem":5456,"rep":9994,"total":16490,"name":"Cherokee, Oklahoma","coordinates":[-94.99679,35.90436]}, {"dem":7016,"rep":7918,"total":16488,"name":"Franklin, Maine","coordinates":[-70.41493,44.97672]}, {"dem":5666,"rep":9880,"total":16465,"name":"Gratiot, Michigan","coordinates":[-84.60469,43.29232]}, {"dem":8619,"rep":6376,"total":16452,"name":"Silver Bow, Montana","coordinates":[-112.66007,45.89623]}, {"dem":11690,"rep":3897,"total":16433,"name":"Santa Cruz, Arizona","coordinates":[-110.84522,31.52573]}, {"dem":4002,"rep":11994,"total":16433,"name":"Navarro, Texas","coordinates":[-96.4769,32.04844]}, {"dem":4374,"rep":11532,"total":16404,"name":"Franklin, Tennessee","coordinates":[-86.0992,35.15592]}, {"dem":4470,"rep":10936,"total":16380,"name":"Orleans, New York","coordinates":[-78.22972,43.50228]}, {"dem":6075,"rep":9093,"total":16365,"name":"Washington, Maine","coordinates":[-67.60935,44.967]}, {"dem":4002,"rep":11725,"total":16363,"name":"Snyder, Pennsylvania","coordinates":[-77.07292,40.7554]}, {"dem":8043,"rep":8009,"total":16310,"name":"Pike, Mississippi","coordinates":[-90.39772,31.17751]}, {"dem":4025,"rep":11635,"total":16296,"name":"McKean, Pennsylvania","coordinates":[-78.57246,41.81459]}, {"dem":4146,"rep":11546,"total":16277,"name":"Greenup, Kentucky","coordinates":[-82.93381,38.56356]}, {"dem":2483,"rep":13190,"total":16243,"name":"Habersham, Georgia","coordinates":[-83.52587,34.63439]}, {"dem":4706,"rep":10710,"total":16205,"name":"Clark, Kentucky","coordinates":[-84.14511,37.97031]}, {"dem":6419,"rep":9157,"total":16184,"name":"Prince George, Virginia","coordinates":[-77.22099,37.18732]}, {"dem":9557,"rep":5100,"total":16174,"name":"Summit, Colorado","coordinates":[-106.13755,39.62102]}, {"dem":6215,"rep":8803,"total":16151,"name":"Lee, Iowa","coordinates":[-91.47715,40.64758]}, {"dem":9556,"rep":6134,"total":16143,"name":"Liberty, Georgia","coordinates":[-81.45787,31.80745]}, {"dem":2913,"rep":12164,"total":16131,"name":"Lincoln, Nebraska","coordinates":[-100.74448,41.05032]}, {"dem":7970,"rep":7697,"total":16116,"name":"Baldwin, Georgia","coordinates":[-83.25545,33.05948]}, {"dem":5452,"rep":9613,"total":16114,"name":"Brown, South Dakota","coordinates":[-98.35217,45.58925]}, {"dem":2926,"rep":12235,"total":16111,"name":"Boone, Arkansas","coordinates":[-93.07923,36.30429]}, {"dem":4273,"rep":11294,"total":16091,"name":"Miller, Arkansas","coordinates":[-93.9015,33.3055]}, {"dem":6041,"rep":8808,"total":16051,"name":"Freeborn, Minnesota","coordinates":[-93.35028,43.6742]}, {"dem":2553,"rep":12881,"total":16051,"name":"Laclede, Missouri","coordinates":[-92.59484,37.65969]}, {"dem":4749,"rep":10367,"total":16049,"name":"Calloway, Kentucky","coordinates":[-88.27408,36.62097]}, {"dem":3506,"rep":11649,"total":16043,"name":"Huntington, Indiana","coordinates":[-85.47859,40.82639]}, {"dem":8324,"rep":7320,"total":16043,"name":"Iberville, Louisiana","coordinates":[-91.36584,30.27062]}, {"dem":2380,"rep":13209,"total":16013,"name":"Upshur, Texas","coordinates":[-94.94118,32.73534]}, {"dem":4949,"rep":9982,"total":15999,"name":"Cass, Minnesota","coordinates":[-94.3337,46.95174]}, {"dem":3134,"rep":11705,"total":15978,"name":"Elbert, Colorado","coordinates":[-104.11407,39.31515]}, {"dem":2352,"rep":13181,"total":15955,"name":"Cooke, Texas","coordinates":[-97.21034,33.63919]}, {"dem":8410,"rep":6964,"total":15952,"name":"Crittenden, Arkansas","coordinates":[-90.31533,35.21187]}, {"dem":2387,"rep":13267,"total":15940,"name":"Covington, Alabama","coordinates":[-86.44872,31.24398]}, {"dem":3878,"rep":11297,"total":15924,"name":"Cheatham, Tennessee","coordinates":[-87.1008,36.25516]}, {"dem":4579,"rep":10692,"total":15917,"name":"Huron, Michigan","coordinates":[-82.85704,43.90761]}, {"dem":7058,"rep":8550,"total":15897,"name":"Bladen, North Carolina","coordinates":[-78.53948,34.59193]}, {"dem":5524,"rep":10167,"total":15884,"name":"Monroe, Mississippi","coordinates":[-88.48503,33.89002]}, {"dem":4053,"rep":10988,"total":15876,"name":"Lafayette, Missouri","coordinates":[-93.80263,39.0687]}, {"dem":3080,"rep":11336,"total":15832,"name":"Morton, North Dakota","coordinates":[-101.29826,46.71081]}, {"dem":6740,"rep":8583,"total":15818,"name":"Accomack, Virginia","coordinates":[-75.7578,37.76594]}, {"dem":4960,"rep":10237,"total":15815,"name":"St. Bernard, Louisiana","coordinates":[-89.26349,29.91811]}, {"dem":6133,"rep":8492,"total":15797,"name":"Fulton, Illinois","coordinates":[-90.20226,40.46524]}, {"dem":3915,"rep":11111,"total":15784,"name":"Warren, Missouri","coordinates":[-91.1593,38.7619]}, {"dem":4482,"rep":10849,"total":15764,"name":"Greene, Pennsylvania","coordinates":[-80.22565,39.8477]}, {"dem":3423,"rep":11555,"total":15717,"name":"Mayes, Oklahoma","coordinates":[-95.23563,36.3038]}, {"dem":3311,"rep":11826,"total":15716,"name":"Delaware, Oklahoma","coordinates":[-94.80821,36.39337]}, {"dem":1201,"rep":8941,"total":15688,"name":"Madison, Idaho","coordinates":[-111.65699,43.78861]}, {"dem":2821,"rep":12420,"total":15666,"name":"Lawrence, Tennessee","coordinates":[-87.39654,35.22047]}, {"dem":6563,"rep":7952,"total":15627,"name":"Coos, New Hampshire","coordinates":[-71.28943,44.65254]}, {"dem":6018,"rep":8475,"total":15624,"name":"Houghton, Michigan","coordinates":[-88.6519,46.99842]}, {"dem":3379,"rep":11358,"total":15623,"name":"Whitley, Indiana","coordinates":[-85.50189,41.13642]}, {"dem":4013,"rep":10785,"total":15552,"name":"Coshocton, Ohio","coordinates":[-81.9301,40.2967]}, {"dem":4918,"rep":9603,"total":15543,"name":"Douglas, Washington","coordinates":[-119.69462,47.74176]}, {"dem":4544,"rep":9933,"total":15529,"name":"Dodge, Nebraska","coordinates":[-96.64585,41.577]}, {"dem":3772,"rep":11077,"total":15516,"name":"Knox, Indiana","coordinates":[-87.42035,38.68839]}, {"dem":5528,"rep":8612,"total":15489,"name":"Lee, Illinois","coordinates":[-89.29936,41.74744]}, {"dem":3721,"rep":11081,"total":15484,"name":"Gibson, Indiana","coordinates":[-87.58052,38.31739]}, {"dem":3992,"rep":10543,"total":15459,"name":"Christian, Illinois","coordinates":[-89.27959,39.54552]}, {"dem":5379,"rep":9122,"total":15456,"name":"Chippewa, Michigan","coordinates":[-84.52062,46.32181]}, {"dem":8423,"rep":5953,"total":15411,"name":"Manassas, Virginia","coordinates":[-77.48263,38.7468]}, {"dem":5057,"rep":9719,"total":15396,"name":"Amherst, Virginia","coordinates":[-79.15466,37.6293]}, {"dem":7732,"rep":7386,"total":15395,"name":"Clarendon, South Carolina","coordinates":[-80.21788,33.66468]}, {"dem":4744,"rep":10022,"total":15394,"name":"Clinton, Pennsylvania","coordinates":[-77.69636,41.26262]}, {"dem":3395,"rep":11486,"total":15355,"name":"Bedford, Tennessee","coordinates":[-86.45829,35.51366]}, {"dem":4348,"rep":10512,"total":15351,"name":"Wakulla, Florida","coordinates":[-84.37484,30.13943]}, {"dem":4290,"rep":10357,"total":15337,"name":"Fayette, West Virginia","coordinates":[-81.08605,38.03093]}, {"dem":4436,"rep":10000,"total":15298,"name":"Wexford, Michigan","coordinates":[-85.57004,44.33137]}, {"dem":4023,"rep":10208,"total":15269,"name":"Livingston, Illinois","coordinates":[-88.55285,40.89437]}, {"dem":10668,"rep":2727,"total":15260,"name":"Taos, New Mexico","coordinates":[-105.63798,36.57652]}, {"dem":6245,"rep":8413,"total":15225,"name":"Dorchester, Maryland","coordinates":[-76.04743,38.42919]}, {"dem":4458,"rep":10550,"total":15193,"name":"Lincoln, Mississippi","coordinates":[-90.45356,31.53521]}, {"dem":3357,"rep":11152,"total":15182,"name":"Wayne, West Virginia","coordinates":[-82.42266,38.14364]}, {"dem":4014,"rep":10529,"total":15173,"name":"Bryan, Georgia","coordinates":[-81.43854,32.01796]}, {"dem":4172,"rep":10322,"total":15167,"name":"Pulaski, Virginia","coordinates":[-80.71344,37.06338]}, {"dem":2701,"rep":12086,"total":15163,"name":"Wise, Virginia","coordinates":[-82.62156,36.97456]}, {"dem":3362,"rep":11059,"total":15156,"name":"Montgomery, Indiana","coordinates":[-86.89271,40.04029]}, {"dem":5594,"rep":8715,"total":15149,"name":"Wapello, Iowa","coordinates":[-92.40946,41.03127]}, {"dem":2535,"rep":11115,"total":15095,"name":"Park, Wyoming","coordinates":[-109.59359,44.49238]}, {"dem":2393,"rep":12238,"total":15078,"name":"Beauregard, Louisiana","coordinates":[-93.34025,30.64501]}, {"dem":7431,"rep":7449,"total":15064,"name":"Panola, Mississippi","coordinates":[-89.96306,34.3652]}, {"dem":9953,"rep":4864,"total":15054,"name":"Williamsburg, South Carolina","coordinates":[-79.71647,33.62646]}, {"dem":3991,"rep":10003,"total":15022,"name":"Miami, Kansas","coordinates":[-94.83296,38.56677]}, {"dem":4138,"rep":10228,"total":14995,"name":"Perry, Ohio","coordinates":[-82.23795,39.74318]}, {"dem":4623,"rep":9182,"total":14971,"name":"Le Sueur, Minnesota","coordinates":[-93.73014,44.37342]}, {"dem":6285,"rep":8288,"total":14945,"name":"Mecklenburg, Virginia","coordinates":[-78.36895,36.68725]}, {"dem":5068,"rep":8668,"total":14916,"name":"Harvey, Kansas","coordinates":[-97.4367,38.05014]}, {"dem":5199,"rep":8624,"total":14891,"name":"Crawford, Kansas","coordinates":[-94.85389,37.50582]}, {"dem":4208,"rep":10360,"total":14882,"name":"Evangeline, Louisiana","coordinates":[-92.40408,30.72069]}, {"dem":9592,"rep":3599,"total":14878,"name":"Rio Arriba, New Mexico","coordinates":[-106.69398,36.50966]}, {"dem":6432,"rep":7147,"total":14863,"name":"Caroline, Virginia","coordinates":[-77.35234,38.03031]}, {"dem":4605,"rep":9935,"total":14845,"name":"Escambia, Alabama","coordinates":[-87.1684,31.12228]}, {"dem":8023,"rep":6587,"total":14839,"name":"Marshall, Mississippi","coordinates":[-89.50423,34.76618]}, {"dem":3637,"rep":10431,"total":14831,"name":"Pontotoc, Oklahoma","coordinates":[-96.69197,34.72144]}, {"dem":3627,"rep":10833,"total":14829,"name":"Lawrence, Alabama","coordinates":[-87.32186,34.52977]}, {"dem":3382,"rep":10945,"total":14828,"name":"Washington, Texas","coordinates":[-96.41027,30.21507]}, {"dem":4696,"rep":9076,"total":14800,"name":"Morgan, Illinois","coordinates":[-90.205,39.71766]}, {"dem":4712,"rep":8979,"total":14796,"name":"Polk, Minnesota","coordinates":[-96.40002,47.77425]}, {"dem":2684,"rep":11819,"total":14783,"name":"Alcorn, Mississippi","coordinates":[-88.5811,34.88656]}, {"dem":6774,"rep":7239,"total":14757,"name":"Leelanau, Michigan","coordinates":[-86.05157,45.14618]}, {"dem":4238,"rep":10149,"total":14732,"name":"Wharton, Texas","coordinates":[-96.22967,29.27848]}, {"dem":3356,"rep":10637,"total":14715,"name":"Putnam, Indiana","coordinates":[-86.85337,39.66554]}, {"dem":5370,"rep":8400,"total":14706,"name":"Lincoln, Wisconsin","coordinates":[-89.7423,45.33841]}, {"dem":4877,"rep":9090,"total":14698,"name":"Alpena, Michigan","coordinates":[-83.42657,44.89495]}, {"dem":5281,"rep":8505,"total":14685,"name":"Mason, Michigan","coordinates":[-86.75081,43.99663]}, {"dem":7541,"rep":5007,"total":14649,"name":"Orange, Vermont","coordinates":[-72.36968,44.00339]}, {"dem":2710,"rep":11428,"total":14605,"name":"Barry, Missouri","coordinates":[-93.83433,36.69937]}, {"dem":3071,"rep":10720,"total":14600,"name":"Greene, Arkansas","coordinates":[-90.56634,36.1206]}, {"dem":5137,"rep":8674,"total":14589,"name":"Charlevoix, Michigan","coordinates":[-85.45039,45.51316]}, {"dem":3744,"rep":10133,"total":14566,"name":"Steuben, Indiana","coordinates":[-85.0024,41.64346]}, {"dem":2927,"rep":10266,"total":14510,"name":"Sheridan, Wyoming","coordinates":[-106.88121,44.78136]}, {"dem":3603,"rep":9745,"total":14444,"name":"Teller, Colorado","coordinates":[-105.18736,38.86997]}, {"dem":3061,"rep":10888,"total":14437,"name":"Sequoyah, Oklahoma","coordinates":[-94.75075,35.50243]}, {"dem":2646,"rep":10965,"total":14433,"name":"Platte, Nebraska","coordinates":[-97.51346,41.57686]}, {"dem":3853,"rep":10025,"total":14426,"name":"Elk, Pennsylvania","coordinates":[-78.65393,41.42733]}, {"dem":2711,"rep":10628,"total":14343,"name":"Madison, Nebraska","coordinates":[-97.60685,41.90992]}, {"dem":3207,"rep":10076,"total":14317,"name":"Scotts Bluff, Nebraska","coordinates":[-103.70154,41.85033]}, {"dem":3080,"rep":10775,"total":14277,"name":"Jefferson Davis, Louisiana","coordinates":[-92.81622,30.26952]}, {"dem":8569,"rep":5444,"total":14276,"name":"Marion, South Carolina","coordinates":[-79.354,34.08361]}, {"dem":4347,"rep":9584,"total":14219,"name":"Tift, Georgia","coordinates":[-83.52593,31.457]}, {"dem":2867,"rep":11014,"total":14215,"name":"Polk, Georgia","coordinates":[-85.18833,33.99601]}, {"dem":6352,"rep":6996,"total":14213,"name":"Vernon, Wisconsin","coordinates":[-90.82198,43.59936]}, {"dem":3759,"rep":9701,"total":14209,"name":"Cass, Indiana","coordinates":[-86.35516,40.75379]}, {"dem":5541,"rep":7484,"total":14196,"name":"Boone, Iowa","coordinates":[-93.93835,42.03864]}, {"dem":3439,"rep":10023,"total":14194,"name":"Randolph, Illinois","coordinates":[-89.8212,38.05651]}, {"dem":6579,"rep":7265,"total":14192,"name":"Chester, South Carolina","coordinates":[-81.16124,34.68934]}, {"dem":2860,"rep":10844,"total":14181,"name":"Cherokee, North Carolina","coordinates":[-84.06144,35.13714]}, {"dem":3170,"rep":10646,"total":14143,"name":"Lee, Georgia","coordinates":[-84.14668,31.81841]}, {"dem":4009,"rep":9368,"total":14113,"name":"Caroline, Maryland","coordinates":[-75.83166,38.87153]}, {"dem":6445,"rep":5534,"total":14075,"name":"Caledonia, Vermont","coordinates":[-72.11216,44.46879]}, {"dem":3765,"rep":9556,"total":14066,"name":"Greenbrier, West Virginia","coordinates":[-80.45058,37.92441]}, {"dem":4240,"rep":8831,"total":14050,"name":"Schoharie, New York","coordinates":[-74.43817,42.59129]}, {"dem":1979,"rep":11651,"total":14038,"name":"Pickens, Georgia","coordinates":[-84.49035,34.45674]}, {"dem":4889,"rep":8384,"total":14037,"name":"Goochland, Virginia","coordinates":[-77.91762,37.71881]}, {"dem":1621,"rep":12017,"total":14026,"name":"Brown, Texas","coordinates":[-98.99845,31.76413]}, {"dem":2430,"rep":10854,"total":14025,"name":"Lincoln, Oklahoma","coordinates":[-96.88139,35.70311]}, {"dem":2567,"rep":10776,"total":14011,"name":"Garrett, Maryland","coordinates":[-79.27461,39.54729]}, {"dem":7600,"rep":5230,"total":13986,"name":"Routt, Colorado","coordinates":[-106.9877,40.48366]}, {"dem":5697,"rep":7236,"total":13980,"name":"Seneca, New York","coordinates":[-76.82708,42.78229]}, {"dem":4385,"rep":8944,"total":13949,"name":"Okmulgee, Oklahoma","coordinates":[-95.96594,35.6435]}, {"dem":3756,"rep":9301,"total":13932,"name":"Henry, Ohio","coordinates":[-84.06889,41.33158]}, {"dem":7319,"rep":6256,"total":13928,"name":"Scotland, North Carolina","coordinates":[-79.47733,34.84002]}, {"dem":4094,"rep":9588,"total":13915,"name":"Coffee, Georgia","coordinates":[-82.84494,31.54924]}, {"dem":5784,"rep":7843,"total":13900,"name":"Chambers, Alabama","coordinates":[-85.39403,32.9155]}, {"dem":2160,"rep":11210,"total":13893,"name":"Erath, Texas","coordinates":[-98.2205,32.23666]}, {"dem":4678,"rep":8232,"total":13844,"name":"Benton, Iowa","coordinates":[-92.05763,42.09254]}, {"dem":7757,"rep":5874,"total":13836,"name":"Adams, Mississippi","coordinates":[-91.35179,31.48622]}, {"dem":9046,"rep":4590,"total":13824,"name":"Bolivar, Mississippi","coordinates":[-90.88411,33.79913]}, {"dem":2804,"rep":10478,"total":13818,"name":"Bryan, Oklahoma","coordinates":[-96.26413,33.964]}, {"dem":4580,"rep":8191,"total":13811,"name":"Pine, Minnesota","coordinates":[-92.76309,46.10094]}, {"dem":5768,"rep":6538,"total":13803,"name":"Tillamook, Oregon","coordinates":[-123.75929,45.45588]}, {"dem":2929,"rep":10277,"total":13801,"name":"Greene, Indiana","coordinates":[-87.00477,39.04714]}, {"dem":12021,"rep":1451,"total":13786,"name":"Petersburg, Virginia","coordinates":[-77.39236,37.20473]}, {"dem":3763,"rep":8708,"total":13779,"name":"Brown, Minnesota","coordinates":[-94.73364,44.24654]}, {"dem":2067,"rep":11312,"total":13774,"name":"Whitley, Kentucky","coordinates":[-84.14464,36.75802]}, {"dem":2697,"rep":10469,"total":13770,"name":"Van Wert, Ohio","coordinates":[-84.58577,40.85552]}, {"dem":2631,"rep":10438,"total":13763,"name":"Polk, Missouri","coordinates":[-93.40081,37.61676]}, {"dem":3226,"rep":9949,"total":13693,"name":"Jackson, Ohio","coordinates":[-82.61414,39.01347]}, {"dem":5636,"rep":7364,"total":13675,"name":"Trempealeau, Wisconsin","coordinates":[-91.35886,44.30305]}, {"dem":4651,"rep":8618,"total":13673,"name":"Atascosa, Texas","coordinates":[-98.53538,28.89147]}, {"dem":4302,"rep":8683,"total":13672,"name":"Cheboygan, Michigan","coordinates":[-84.49543,45.47602]}, {"dem":2559,"rep":10663,"total":13668,"name":"Carroll, Virginia","coordinates":[-80.72783,36.73196]}, {"dem":3959,"rep":9356,"total":13653,"name":"Okeechobee, Florida","coordinates":[-80.88738,27.38559]}, {"dem":3463,"rep":9898,"total":13624,"name":"Colquitt, Georgia","coordinates":[-83.76977,31.1897]}, {"dem":6964,"rep":5890,"total":13617,"name":"Val Verde, Texas","coordinates":[-101.14332,29.87528]}, {"dem":2881,"rep":9936,"total":13614,"name":"Independence, Arkansas","coordinates":[-91.55994,35.73749]}, {"dem":3535,"rep":9540,"total":13612,"name":"Warren, Tennessee","coordinates":[-85.77734,35.67824]}, {"dem":4770,"rep":8169,"total":13612,"name":"Vilas, Wisconsin","coordinates":[-89.50125,46.04984]}, {"dem":5760,"rep":7025,"total":13597,"name":"Fluvanna, Virginia","coordinates":[-78.28349,37.83058]}, {"dem":4227,"rep":8646,"total":13596,"name":"Clark, Wisconsin","coordinates":[-90.60995,44.73934]}, {"dem":10397,"rep":2816,"total":13588,"name":"Maverick, Texas","coordinates":[-100.31667,28.72978]}, {"dem":4448,"rep":8469,"total":13582,"name":"Antrim, Michigan","coordinates":[-85.17563,45.00545]}, {"dem":5765,"rep":7447,"total":13575,"name":"Dinwiddie, Virginia","coordinates":[-77.63549,37.07349]}, {"dem":4958,"rep":7697,"total":13563,"name":"Woodford, Kentucky","coordinates":[-84.74885,38.0431]}, {"dem":4326,"rep":8546,"total":13544,"name":"Jefferson, Indiana","coordinates":[-85.44009,38.7836]}, {"dem":5356,"rep":7208,"total":13538,"name":"Bremer, Iowa","coordinates":[-92.32735,42.78089]}, {"dem":2510,"rep":10707,"total":13538,"name":"Hopkins, Texas","coordinates":[-95.56543,33.14896]}, {"dem":3302,"rep":9287,"total":13513,"name":"Adams, Nebraska","coordinates":[-98.50004,40.52063]}, {"dem":5165,"rep":8068,"total":13500,"name":"De Soto, Louisiana","coordinates":[-93.74079,32.05924]}, {"dem":2922,"rep":9876,"total":13488,"name":"Pulaski, Missouri","coordinates":[-92.20702,37.82483]}, {"dem":2766,"rep":9975,"total":13482,"name":"Miami, Indiana","coordinates":[-86.04425,40.77288]}, {"dem":3018,"rep":9821,"total":13468,"name":"Wabash, Indiana","coordinates":[-85.79519,40.84374]}, {"dem":3500,"rep":9412,"total":13424,"name":"Ashe, North Carolina","coordinates":[-81.49933,36.44346]}, {"dem":2590,"rep":10609,"total":13419,"name":"Jasper, Texas","coordinates":[-94.02229,30.75293]}, {"dem":4249,"rep":8505,"total":13389,"name":"Clare, Michigan","coordinates":[-84.83832,43.99113]}, {"dem":3329,"rep":9382,"total":13378,"name":"Jasper, Indiana","coordinates":[-87.11881,41.01768]}, {"dem":3121,"rep":9035,"total":13370,"name":"Curry, New Mexico","coordinates":[-103.34605,34.57298]}, {"dem":4345,"rep":8345,"total":13361,"name":"Iosco, Michigan","coordinates":[-82.84944,44.32948]}, {"dem":2554,"rep":10398,"total":13348,"name":"Lincoln, Tennessee","coordinates":[-86.5934,35.14278]}, {"dem":2770,"rep":10046,"total":13343,"name":"Wythe, Virginia","coordinates":[-81.083,36.89986]}, {"dem":2816,"rep":10180,"total":13336,"name":"Dyer, Tennessee","coordinates":[-89.3983,36.05419]}, {"dem":1876,"rep":11079,"total":13291,"name":"Stoddard, Missouri","coordinates":[-89.94748,36.85155]}, {"dem":2918,"rep":9666,"total":13216,"name":"Marshall, West Virginia","coordinates":[-80.67179,39.85442]}, {"dem":2288,"rep":10446,"total":13214,"name":"Gillespie, Texas","coordinates":[-98.94185,30.32509]}, {"dem":5670,"rep":7061,"total":13204,"name":"Mississippi, Arkansas","coordinates":[-90.0522,35.76694]}, {"dem":2885,"rep":9680,"total":13190,"name":"Plymouth, Iowa","coordinates":[-96.21586,42.73758]}, {"dem":2586,"rep":10005,"total":13185,"name":"Wells, Indiana","coordinates":[-85.21297,40.73527]}, {"dem":4776,"rep":7530,"total":13181,"name":"Lake, Montana","coordinates":[-114.08368,47.6429]}, {"dem":5056,"rep":7693,"total":13168,"name":"Pike, Alabama","coordinates":[-85.9416,31.79865]}, {"dem":3923,"rep":8580,"total":13165,"name":"Dickinson, Michigan","coordinates":[-87.86612,46.01282]}, {"dem":3811,"rep":8837,"total":13144,"name":"Wyoming, Pennsylvania","coordinates":[-76.00873,41.52517]}, {"dem":5288,"rep":6795,"total":13092,"name":"McDonough, Illinois","coordinates":[-90.67895,40.4558]}, {"dem":2805,"rep":9648,"total":13090,"name":"Adams, Indiana","coordinates":[-84.93613,40.74573]}, {"dem":3154,"rep":9254,"total":13074,"name":"Carroll, Ohio","coordinates":[-81.09078,40.57988]}, {"dem":2504,"rep":9750,"total":13064,"name":"Iroquois, Illinois","coordinates":[-87.8336,40.74886]}, {"dem":3272,"rep":9393,"total":13060,"name":"Muhlenberg, Kentucky","coordinates":[-87.13409,37.21381]}, {"dem":4287,"rep":8141,"total":13041,"name":"Roscommon, Michigan","coordinates":[-84.61127,44.33951]}, {"dem":5749,"rep":7140,"total":13031,"name":"Clarke, Alabama","coordinates":[-87.81862,31.68552]}, {"dem":3710,"rep":8340,"total":13017,"name":"Mille Lacs, Minnesota","coordinates":[-93.63299,45.92904]}, {"dem":1432,"rep":11274,"total":12984,"name":"Marion, Alabama","coordinates":[-87.88155,34.13821]}, {"dem":2386,"rep":10336,"total":12984,"name":"Pontotoc, Mississippi","coordinates":[-89.03723,34.22708]}, {"dem":6741,"rep":6103,"total":12982,"name":"Copiah, Mississippi","coordinates":[-90.44875,31.86691]}, {"dem":3504,"rep":8630,"total":12978,"name":"Montgomery, Illinois","coordinates":[-89.47814,39.22806]}, {"dem":2547,"rep":10108,"total":12970,"name":"Hill, Texas","coordinates":[-97.13066,31.98268]}, {"dem":3249,"rep":8431,"total":12968,"name":"Union, Oregon","coordinates":[-117.99914,45.30408]}, {"dem":4281,"rep":8040,"total":12946,"name":"Boyle, Kentucky","coordinates":[-84.86835,37.6181]}, {"dem":3063,"rep":9508,"total":12945,"name":"Henry, Tennessee","coordinates":[-88.30028,36.32529]}, {"dem":2994,"rep":9419,"total":12938,"name":"Marion, Missouri","coordinates":[-91.63537,39.80753]}, {"dem":3484,"rep":8452,"total":12933,"name":"Cass, Nebraska","coordinates":[-96.1406,40.90987]}, {"dem":2628,"rep":9822,"total":12931,"name":"Gallia, Ohio","coordinates":[-82.30174,38.81704]}, {"dem":2665,"rep":9750,"total":12890,"name":"Smyth, Virginia","coordinates":[-81.53978,36.84231]}, {"dem":3973,"rep":7853,"total":12858,"name":"Montezuma, Colorado","coordinates":[-108.59578,37.33802]}, {"dem":3775,"rep":8497,"total":12838,"name":"Hocking, Ohio","coordinates":[-82.48344,39.49034]}, {"dem":6276,"rep":5288,"total":12811,"name":"Grant, New Mexico","coordinates":[-108.3815,32.73208]}, {"dem":2471,"rep":9806,"total":12810,"name":"Ripley, Indiana","coordinates":[-85.26049,39.10022]}, {"dem":1735,"rep":10069,"total":12807,"name":"Williams, North Dakota","coordinates":[-103.50133,48.35576]}, {"dem":995,"rep":9810,"total":12797,"name":"Uintah, Utah","coordinates":[-109.51774,40.12588]}, {"dem":1965,"rep":10477,"total":12773,"name":"Gilmer, Georgia","coordinates":[-84.45462,34.6905]}, {"dem":7241,"rep":3570,"total":12762,"name":"Lamoille, Vermont","coordinates":[-72.63892,44.6037]}, {"dem":3226,"rep":8549,"total":12742,"name":"McPherson, Kansas","coordinates":[-97.64748,38.39581]}, {"dem":5383,"rep":6927,"total":12712,"name":"West Baton Rouge, Louisiana","coordinates":[-91.3098,30.46405]}, {"dem":3262,"rep":8909,"total":12702,"name":"Hancock, West Virginia","coordinates":[-80.57016,40.51695]}, {"dem":3571,"rep":8832,"total":12687,"name":"Monroe, Georgia","coordinates":[-83.92293,33.01743]}, {"dem":4879,"rep":6748,"total":12680,"name":"Brookings, South Dakota","coordinates":[-96.79779,44.37667]}, {"dem":2913,"rep":9163,"total":12669,"name":"Currituck, North Carolina","coordinates":[-75.94122,36.37217]}, {"dem":2470,"rep":9538,"total":12659,"name":"Preston, West Virginia","coordinates":[-79.66886,39.46902]}, {"dem":2112,"rep":10294,"total":12634,"name":"Baker, Florida","coordinates":[-82.30228,30.32444]}, {"dem":7314,"rep":3921,"total":12627,"name":"Teton, Wyoming","coordinates":[-110.42608,44.04866]}, {"dem":3551,"rep":8270,"total":12621,"name":"Cowley, Kansas","coordinates":[-96.83724,37.2345]}, {"dem":4300,"rep":7212,"total":12611,"name":"Curry, Oregon","coordinates":[-124.21092,42.46643]}, {"dem":4979,"rep":6915,"total":12599,"name":"Manistee, Michigan","coordinates":[-86.60296,44.35038]}, {"dem":3961,"rep":8305,"total":12551,"name":"Jones, Georgia","coordinates":[-83.56219,33.02166]}, {"dem":3556,"rep":8266,"total":12538,"name":"Otsego, Michigan","coordinates":[-84.5766,45.02178]}, {"dem":2248,"rep":9870,"total":12532,"name":"Campbell, Tennessee","coordinates":[-84.15924,36.40159]}, {"dem":3794,"rep":8124,"total":12472,"name":"Gladwin, Michigan","coordinates":[-84.38981,43.98975]}, {"dem":3521,"rep":8404,"total":12467,"name":"Posey, Indiana","coordinates":[-87.86865,38.02761]}, {"dem":1800,"rep":10341,"total":12458,"name":"Murray, Georgia","coordinates":[-84.73798,34.79709]}, {"dem":2220,"rep":9619,"total":12425,"name":"Lumpkin, Georgia","coordinates":[-83.99892,34.56814]}, {"dem":3313,"rep":8181,"total":12401,"name":"Logan, Illinois","coordinates":[-89.3653,40.12927]}, {"dem":6694,"rep":5420,"total":12379,"name":"Jim Wells, Texas","coordinates":[-98.09081,27.73351]}, {"dem":2092,"rep":9897,"total":12359,"name":"Logan, West Virginia","coordinates":[-81.94085,37.83059]}, {"dem":2391,"rep":9726,"total":12344,"name":"Cass, Texas","coordinates":[-94.35757,33.08369]}, {"dem":1753,"rep":9755,"total":12322,"name":"Stark, North Dakota","coordinates":[-102.66202,46.81703]}, {"dem":2920,"rep":8717,"total":12294,"name":"Hardin, Ohio","coordinates":[-83.66407,40.66041]}, {"dem":4649,"rep":6552,"total":12288,"name":"Lyon, Kansas","coordinates":[-96.16164,38.4554]}, {"dem":3191,"rep":8104,"total":12282,"name":"Meeker, Minnesota","coordinates":[-94.52734,45.12315]}, {"dem":2320,"rep":9637,"total":12274,"name":"Austin, Texas","coordinates":[-96.27016,29.8919]}, {"dem":6669,"rep":4809,"total":12260,"name":"Iowa, Wisconsin","coordinates":[-90.13369,43.00102]}, {"dem":2426,"rep":9526,"total":12249,"name":"Obion, Tennessee","coordinates":[-89.15002,36.35799]}, {"dem":2330,"rep":9521,"total":12246,"name":"Russell, Virginia","coordinates":[-82.09593,36.93341]}, {"dem":3546,"rep":8118,"total":12242,"name":"New Kent, Virginia","coordinates":[-76.99932,37.51015]}, {"dem":3026,"rep":8660,"total":12231,"name":"Meade, Kentucky","coordinates":[-86.20086,37.96747]}, {"dem":4202,"rep":7226,"total":12225,"name":"Salem, Virginia","coordinates":[-80.05524,37.28533]}, {"dem":3825,"rep":7256,"total":12215,"name":"Lyon, Minnesota","coordinates":[-95.84726,44.40919]}, {"dem":3500,"rep":8366,"total":12196,"name":"Matagorda, Texas","coordinates":[-96.00153,28.77476]}, {"dem":2663,"rep":9020,"total":12187,"name":"Jackson, West Virginia","coordinates":[-81.67771,38.83423]}, {"dem":3440,"rep":8513,"total":12184,"name":"Ware, Georgia","coordinates":[-82.4215,31.05088]}, {"dem":2772,"rep":9008,"total":12184,"name":"Weakley, Tennessee","coordinates":[-88.72119,36.30359]}, {"dem":2637,"rep":8511,"total":12172,"name":"Crook, Oregon","coordinates":[-120.37158,44.16305]}, {"dem":3301,"rep":8025,"total":12134,"name":"Graham, Arizona","coordinates":[-109.87831,32.93182]}, {"dem":1981,"rep":9791,"total":12126,"name":"Cocke, Tennessee","coordinates":[-83.11922,35.91619]}, {"dem":3063,"rep":6115,"total":12120,"name":"Wasatch, Utah","coordinates":[-111.16156,40.33488]}, {"dem":2924,"rep":8913,"total":12098,"name":"Bradford, Florida","coordinates":[-82.16667,29.95238]}, {"dem":4729,"rep":7061,"total":12092,"name":"Union, South Carolina","coordinates":[-81.61589,34.69039]}, {"dem":4795,"rep":6691,"total":12092,"name":"Caldwell, Texas","coordinates":[-97.62814,29.83239]}, {"dem":2101,"rep":9458,"total":12085,"name":"Cleburne, Arkansas","coordinates":[-92.05995,35.56631]}, {"dem":6418,"rep":5456,"total":12085,"name":"St. James, Louisiana","coordinates":[-90.79395,30.02477]}, {"dem":1963,"rep":9852,"total":12063,"name":"Union, Georgia","coordinates":[-83.98925,34.83333]}, {"dem":4007,"rep":7341,"total":12059,"name":"King George, Virginia","coordinates":[-77.16263,38.27717]}, {"dem":5185,"rep":5159,"total":12047,"name":"Orleans, Vermont","coordinates":[-72.25163,44.82844]}, {"dem":2132,"rep":9548,"total":12044,"name":"Fannin, Texas","coordinates":[-96.10498,33.59116]}, {"dem":2197,"rep":9466,"total":12040,"name":"Franklin, Alabama","coordinates":[-87.84281,34.44198]}, {"dem":1761,"rep":9885,"total":12012,"name":"Knox, Kentucky","coordinates":[-83.85555,36.8885]}, {"dem":2637,"rep":8679,"total":12004,"name":"Montgomery, Kansas","coordinates":[-95.7424,37.18953]}, {"dem":3792,"rep":7669,"total":11999,"name":"Waushara, Wisconsin","coordinates":[-89.23978,44.11282]}, {"dem":2425,"rep":9201,"total":11998,"name":"Madison, Georgia","coordinates":[-83.20373,34.12852]}, {"dem":2783,"rep":8485,"total":11993,"name":"Todd, Minnesota","coordinates":[-94.90057,46.06656]}, {"dem":5846,"rep":5897,"total":11964,"name":"Martin, North Carolina","coordinates":[-77.1196,35.8473]}, {"dem":4781,"rep":5833,"total":11964,"name":"Wasco, Oregon","coordinates":[-121.16506,45.16453]}, {"dem":3151,"rep":8145,"total":11960,"name":"Morgan, Colorado","coordinates":[-103.81221,40.26315]}, {"dem":2742,"rep":8466,"total":11947,"name":"Ellis, Kansas","coordinates":[-99.31731,38.91459]}, {"dem":3149,"rep":8172,"total":11944,"name":"Hot Spring, Arkansas","coordinates":[-92.94414,34.31517]}, {"dem":2819,"rep":8531,"total":11936,"name":"Clinton, Indiana","coordinates":[-86.47756,40.30594]}, {"dem":3973,"rep":7228,"total":11930,"name":"Oceana, Michigan","coordinates":[-86.80757,43.64725]}, {"dem":3539,"rep":7902,"total":11879,"name":"Pike, Ohio","coordinates":[-83.05291,39.07134]}, {"dem":5155,"rep":6502,"total":11852,"name":"Morehouse, Louisiana","coordinates":[-91.80039,32.82]}, {"dem":3356,"rep":7411,"total":11842,"name":"Lawrence, South Dakota","coordinates":[-103.80494,44.34876]}, {"dem":3866,"rep":6989,"total":11832,"name":"Wabasha, Minnesota","coordinates":[-92.23334,44.28969]}, {"dem":1674,"rep":9761,"total":11823,"name":"White, Georgia","coordinates":[-83.74341,34.64377]}, {"dem":1923,"rep":9632,"total":11812,"name":"Fannin, Georgia","coordinates":[-84.31733,34.86654]}, {"dem":1448,"rep":9900,"total":11765,"name":"Dawson, Georgia","coordinates":[-84.17326,34.4426]}, {"dem":4764,"rep":6789,"total":11761,"name":"Pointe Coupee, Louisiana","coordinates":[-91.60462,30.70831]}, {"dem":1525,"rep":9994,"total":11758,"name":"Geneva, Alabama","coordinates":[-85.82102,31.09238]}, {"dem":9289,"rep":2224,"total":11740,"name":"Starr, Texas","coordinates":[-98.74023,26.5309]}, {"dem":4073,"rep":7123,"total":11732,"name":"Juneau, Wisconsin","coordinates":[-90.11398,43.93283]}, {"dem":5834,"rep":5637,"total":11698,"name":"Dillon, South Carolina","coordinates":[-79.37496,34.39017]}, {"dem":3677,"rep":7836,"total":11693,"name":"Marion, Mississippi","coordinates":[-89.82171,31.23016]}, {"dem":3174,"rep":7764,"total":11669,"name":"Codington, South Dakota","coordinates":[-97.19883,44.96628]}, {"dem":4491,"rep":6842,"total":11644,"name":"Edgefield, South Carolina","coordinates":[-81.96824,33.77649]}, {"dem":3926,"rep":7495,"total":11627,"name":"Tate, Mississippi","coordinates":[-89.9431,34.64955]}, {"dem":2223,"rep":8441,"total":11621,"name":"Meade, South Dakota","coordinates":[-102.71416,44.60528]}, {"dem":2050,"rep":9070,"total":11564,"name":"Mineral, West Virginia","coordinates":[-78.95668,39.40478]}, {"dem":4150,"rep":7130,"total":11540,"name":"Montgomery, North Carolina","coordinates":[-79.9066,35.33441]}, {"dem":3423,"rep":7261,"total":11505,"name":"Hubbard, Minnesota","coordinates":[-94.91328,47.09555]}, {"dem":8400,"rep":2477,"total":11502,"name":"Dukes, Massachusetts","coordinates":[-70.70149,41.38096]}, {"dem":2012,"rep":9235,"total":11496,"name":"Union, Mississippi","coordinates":[-89.00233,34.48953]}, {"dem":976,"rep":8436,"total":11475,"name":"Jefferson, Idaho","coordinates":[-112.31858,43.79696]}, {"dem":2852,"rep":8184,"total":11455,"name":"Marshall, Tennessee","coordinates":[-86.76586,35.46834]}, {"dem":3158,"rep":7856,"total":11452,"name":"Montgomery, Kentucky","coordinates":[-83.91241,38.0381]}, {"dem":5956,"rep":5187,"total":11427,"name":"Jasper, South Carolina","coordinates":[-81.02162,32.43059]}, {"dem":2634,"rep":8242,"total":11422,"name":"Anderson, Kentucky","coordinates":[-84.98641,38.00539]}, {"dem":3874,"rep":7393,"total":11419,"name":"Simpson, Mississippi","coordinates":[-89.9177,31.9025]}, {"dem":1750,"rep":9285,"total":11416,"name":"Miller, Missouri","coordinates":[-92.42987,38.21668]}, {"dem":2572,"rep":8276,"total":11384,"name":"Saline, Illinois","coordinates":[-88.54502,37.7515]}, {"dem":2636,"rep":8209,"total":11382,"name":"Washington, Indiana","coordinates":[-86.10475,38.60061]}, {"dem":5254,"rep":5344,"total":11362,"name":"Winneshiek, Iowa","coordinates":[-91.85078,43.29298]}, {"dem":2326,"rep":8659,"total":11359,"name":"Adams, Ohio","coordinates":[-83.47808,38.83446]}, {"dem":1475,"rep":9585,"total":11357,"name":"Haralson, Georgia","coordinates":[-85.22006,33.79516]}, {"dem":4462,"rep":6121,"total":11334,"name":"Jo Daviess, Illinois","coordinates":[-90.21147,42.36239]}, {"dem":3146,"rep":7400,"total":11325,"name":"Lewis, New York","coordinates":[-75.44414,43.78268]}, {"dem":2553,"rep":8320,"total":11306,"name":"Taylor, Kentucky","coordinates":[-85.32805,37.36621]}, {"dem":2306,"rep":8531,"total":11282,"name":"Clay, Indiana","coordinates":[-87.11585,39.39392]}, {"dem":3926,"rep":6783,"total":11269,"name":"Madison, North Carolina","coordinates":[-82.71262,35.8642]}, {"dem":6945,"rep":4027,"total":11267,"name":"Fairfield, South Carolina","coordinates":[-81.127,34.39566]}, {"dem":6707,"rep":3744,"total":11264,"name":"Fredericksburg, Virginia","coordinates":[-77.48665,38.29927]}, {"dem":5333,"rep":5133,"total":11255,"name":"Staunton, Virginia","coordinates":[-79.06187,38.15797]}, {"dem":4888,"rep":5391,"total":11250,"name":"Chaffee, Colorado","coordinates":[-106.31668,38.73822]}, {"dem":2144,"rep":8743,"total":11174,"name":"Fayette, Texas","coordinates":[-96.92123,29.87788]}, {"dem":2739,"rep":7995,"total":11162,"name":"Fayette, Ohio","coordinates":[-83.46189,39.55524]}, {"dem":2264,"rep":8637,"total":11156,"name":"Washington, Florida","coordinates":[-85.66279,30.60221]}, {"dem":2364,"rep":8224,"total":11150,"name":"Jennings, Indiana","coordinates":[-85.6281,38.99622]}, {"dem":7787,"rep":3212,"total":11140,"name":"Leflore, Mississippi","coordinates":[-90.29493,33.54978]}, {"dem":2917,"rep":7970,"total":11137,"name":"Giles, Tennessee","coordinates":[-87.03531,35.20272]}, {"dem":2121,"rep":8490,"total":11127,"name":"Decatur, Indiana","coordinates":[-85.49983,39.30597]}, {"dem":4615,"rep":6195,"total":11115,"name":"Hendry, Florida","coordinates":[-81.15211,26.53996]}, {"dem":4792,"rep":6026,"total":11070,"name":"Caswell, North Carolina","coordinates":[-79.3396,36.39429]}, {"dem":1942,"rep":8660,"total":11062,"name":"Rhea, Tennessee","coordinates":[-84.94954,35.60059]}, {"dem":3872,"rep":6271,"total":11055,"name":"Fillmore, Minnesota","coordinates":[-92.09393,43.67918]}, {"dem":1788,"rep":8720,"total":11054,"name":"Holmes, Ohio","coordinates":[-81.93,40.56559]}, {"dem":1969,"rep":8669,"total":11013,"name":"Franklin, Indiana","coordinates":[-85.06696,39.40976]}, {"dem":2288,"rep":8229,"total":11010,"name":"Shelby, Illinois","coordinates":[-88.79886,39.38492]}, {"dem":5615,"rep":5233,"total":10994,"name":"Marengo, Alabama","coordinates":[-87.79109,32.24759]}, {"dem":2679,"rep":7748,"total":10991,"name":"Jersey, Illinois","coordinates":[-90.36138,39.08019]}, {"dem":5520,"rep":5276,"total":10974,"name":"Sumter, Georgia","coordinates":[-84.20429,32.04226]}, {"dem":2892,"rep":7185,"total":10965,"name":"Franklin, Kansas","coordinates":[-95.27896,38.55801]}, {"dem":1728,"rep":8875,"total":10956,"name":"Texas, Missouri","coordinates":[-91.96447,37.31425]}, {"dem":2210,"rep":7830,"total":10938,"name":"Churchill, Nevada","coordinates":[-118.26416,39.5377]}, {"dem":3475,"rep":7292,"total":10934,"name":"Upson, Georgia","coordinates":[-84.29228,32.88183]}, {"dem":3735,"rep":6768,"total":10934,"name":"Polk, North Carolina","coordinates":[-82.16762,35.2779]}, {"dem":3943,"rep":6173,"total":10929,"name":"Washington, Iowa","coordinates":[-91.72505,41.3294]}, {"dem":6510,"rep":3272,"total":10910,"name":"Hood River, Oregon","coordinates":[-121.65597,45.51177]}, {"dem":3931,"rep":6714,"total":10904,"name":"Assumption, Louisiana","coordinates":[-91.05246,29.89885]}, {"dem":2755,"rep":7778,"total":10899,"name":"Logan, Kentucky","coordinates":[-86.88128,36.8596]}, {"dem":2691,"rep":7972,"total":10894,"name":"Union, Louisiana","coordinates":[-92.37565,32.82934]}, {"dem":5562,"rep":3359,"total":10885,"name":"Los Alamos, New Mexico","coordinates":[-106.30796,35.87004]}, {"dem":2735,"rep":7629,"total":10876,"name":"Randolph, West Virginia","coordinates":[-79.86778,38.78109]}, {"dem":3090,"rep":7104,"total":10869,"name":"Ray, Missouri","coordinates":[-93.99574,39.3084]}, {"dem":2832,"rep":7696,"total":10862,"name":"Marion, Tennessee","coordinates":[-85.61839,35.13342]}, {"dem":2523,"rep":7555,"total":10860,"name":"Saunders, Nebraska","coordinates":[-96.64209,41.22338]}, {"dem":2623,"rep":7424,"total":10832,"name":"Washington, Nebraska","coordinates":[-96.22457,41.53397]}, {"dem":3781,"rep":6778,"total":10818,"name":"Desoto, Florida","coordinates":[-81.80625,27.19058]}, {"dem":3508,"rep":6680,"total":10795,"name":"Rockbridge, Virginia","coordinates":[-79.44775,37.81451]}, {"dem":3741,"rep":6763,"total":10775,"name":"Abbeville, South Carolina","coordinates":[-82.45405,34.22904]}, {"dem":7172,"rep":2688,"total":10774,"name":"San Juan, Washington","coordinates":[-123.10376,48.50719]}, {"dem":4194,"rep":5789,"total":10769,"name":"Klickitat, Washington","coordinates":[-120.7793,45.87044]}, {"dem":1800,"rep":8545,"total":10768,"name":"Daviess, Indiana","coordinates":[-87.07694,38.69608]}, {"dem":3539,"rep":6702,"total":10768,"name":"Menominee, Michigan","coordinates":[-87.50181,45.5362]}, {"dem":3342,"rep":6786,"total":10758,"name":"Carroll, Arkansas","coordinates":[-93.54097,36.33737]}, {"dem":3623,"rep":6616,"total":10758,"name":"Kewaunee, Wisconsin","coordinates":[-87.1633,44.50103]}, {"dem":1372,"rep":9129,"total":10757,"name":"Harlan, Kentucky","coordinates":[-83.22149,36.85922]}, {"dem":5100,"rep":5413,"total":10752,"name":"Peach, Georgia","coordinates":[-83.83197,32.57132]}, {"dem":7285,"rep":2313,"total":10751,"name":"San Miguel, New Mexico","coordinates":[-104.80351,35.47685]}, {"dem":1832,"rep":8602,"total":10740,"name":"Claiborne, Tennessee","coordinates":[-83.66069,36.50157]}, {"dem":2514,"rep":7831,"total":10740,"name":"Page, Virginia","coordinates":[-78.49187,38.6232]}, {"dem":1547,"rep":8953,"total":10733,"name":"Cherokee, Alabama","coordinates":[-85.65424,34.06951]}, {"dem":1802,"rep":8656,"total":10726,"name":"McCurtain, Oklahoma","coordinates":[-94.76608,34.11707]}, {"dem":6416,"rep":3340,"total":10724,"name":"Blaine, Idaho","coordinates":[-113.95537,43.39419]}, {"dem":4620,"rep":5360,"total":10716,"name":"Pacific, Washington","coordinates":[-123.78241,46.55658]}, {"dem":2225,"rep":7612,"total":10693,"name":"Pottawatomie, Kansas","coordinates":[-96.33711,39.38218]}, {"dem":2584,"rep":7631,"total":10690,"name":"Ottawa, Oklahoma","coordinates":[-94.80268,36.83576]}, {"dem":5164,"rep":4790,"total":10667,"name":"Winchester, Virginia","coordinates":[-78.17635,39.17386]}, {"dem":3102,"rep":6527,"total":10654,"name":"Dodge, Minnesota","coordinates":[-92.86935,44.0207]}, {"dem":2619,"rep":7432,"total":10632,"name":"Mahaska, Iowa","coordinates":[-92.63636,41.33079]}, {"dem":2705,"rep":7336,"total":10609,"name":"Osceola, Michigan","coordinates":[-85.32228,43.99755]}, {"dem":4145,"rep":5616,"total":10604,"name":"Houston, Minnesota","coordinates":[-91.50155,43.66698]}, {"dem":2515,"rep":7468,"total":10592,"name":"Wyandot, Ohio","coordinates":[-83.31368,40.83978]}, {"dem":2395,"rep":7740,"total":10585,"name":"Mercer, Kentucky","coordinates":[-84.87969,37.81208]}, {"dem":2360,"rep":8026,"total":10578,"name":"Dunklin, Missouri","coordinates":[-90.06539,36.3069]}, {"dem":1959,"rep":8219,"total":10576,"name":"Grayson, Kentucky","coordinates":[-86.34401,37.45857]}, {"dem":3347,"rep":6900,"total":10573,"name":"Plaquemines, Louisiana","coordinates":[-89.57606,29.28244]}, {"dem":2136,"rep":8158,"total":10572,"name":"Perry, Kentucky","coordinates":[-83.21777,37.24128]}, {"dem":2715,"rep":7679,"total":10553,"name":"Neshoba, Mississippi","coordinates":[-89.11927,32.75251]}, {"dem":1855,"rep":8253,"total":10546,"name":"Garvin, Oklahoma","coordinates":[-97.31272,34.70934]}, {"dem":5859,"rep":4506,"total":10545,"name":"Anson, North Carolina","coordinates":[-80.10976,34.97497]}, {"dem":3309,"rep":6638,"total":10544,"name":"Carroll, Iowa","coordinates":[-94.86764,42.03949]}, {"dem":2104,"rep":7826,"total":10541,"name":"Custer, Oklahoma","coordinates":[-98.99738,35.6456]}, {"dem":2733,"rep":7062,"total":10531,"name":"Martin, Minnesota","coordinates":[-94.53725,43.67711]}, {"dem":2224,"rep":7574,"total":10524,"name":"Lassen, California","coordinates":[-120.62995,40.72108]}, {"dem":7333,"rep":2550,"total":10523,"name":"Pitkin, Colorado","coordinates":[-106.91615,39.21753]}, {"dem":4268,"rep":6122,"total":10522,"name":"Scott, Mississippi","coordinates":[-89.53348,32.41195]}, {"dem":4424,"rep":5970,"total":10513,"name":"Grenada, Mississippi","coordinates":[-89.80274,33.77003]}, {"dem":2465,"rep":7740,"total":10512,"name":"Aransas, Texas","coordinates":[-96.9675,28.12262]}, {"dem":4871,"rep":5454,"total":10469,"name":"Barbour, Alabama","coordinates":[-85.4051,31.87025]}, {"dem":2446,"rep":7517,"total":10458,"name":"Randolph, Indiana","coordinates":[-85.00578,40.16407]}, {"dem":1821,"rep":8273,"total":10454,"name":"Juniata, Pennsylvania","coordinates":[-77.40043,40.53067]}, {"dem":1825,"rep":8299,"total":10447,"name":"Llano, Texas","coordinates":[-98.68469,30.70758]}, {"dem":2246,"rep":7194,"total":10435,"name":"Malheur, Oregon","coordinates":[-117.60319,43.18862]}, {"dem":3421,"rep":6135,"total":10417,"name":"Park, Colorado","coordinates":[-105.71764,39.11891]}, {"dem":1835,"rep":8445,"total":10416,"name":"Panola, Texas","coordinates":[-94.30515,32.16397]}, {"dem":2041,"rep":8153,"total":10413,"name":"Wayne, Georgia","coordinates":[-81.91237,31.54784]}, {"dem":2080,"rep":7942,"total":10398,"name":"Ohio, Kentucky","coordinates":[-86.84487,37.47785]}, {"dem":5954,"rep":4267,"total":10389,"name":"Marlboro, South Carolina","coordinates":[-79.67943,34.60167]}, {"dem":3030,"rep":6827,"total":10387,"name":"Ogemaw, Michigan","coordinates":[-84.12807,44.33328]}, {"dem":2327,"rep":7756,"total":10384,"name":"Carroll, Tennessee","coordinates":[-88.45237,35.96574]}, {"dem":3056,"rep":6753,"total":10354,"name":"Dickinson, Iowa","coordinates":[-95.19605,43.38961]}, {"dem":2038,"rep":8059,"total":10343,"name":"San Jacinto, Texas","coordinates":[-95.16313,30.57438]}, {"dem":872,"rep":9228,"total":10313,"name":"Winston, Alabama","coordinates":[-87.36534,34.15456]}, {"dem":3837,"rep":5824,"total":10310,"name":"Jackson, Iowa","coordinates":[-90.57458,42.16422]}, {"dem":2283,"rep":7529,"total":10309,"name":"Randolph, Missouri","coordinates":[-92.49295,39.43924]}, {"dem":4124,"rep":6020,"total":10286,"name":"Decatur, Georgia","coordinates":[-84.58389,30.88064]}, {"dem":2276,"rep":7587,"total":10278,"name":"Carter, Kentucky","coordinates":[-83.04879,38.30954]}, {"dem":4332,"rep":5795,"total":10271,"name":"Monroe, Alabama","coordinates":[-87.38326,31.58033]}, {"dem":1708,"rep":8284,"total":10270,"name":"Palo Pinto, Texas","coordinates":[-98.31796,32.7522]}, {"dem":1839,"rep":7888,"total":10269,"name":"Barton, Kansas","coordinates":[-98.76783,38.48123]}, {"dem":3970,"rep":5510,"total":10252,"name":"Buchanan, Iowa","coordinates":[-91.83866,42.47032]}, {"dem":4108,"rep":5539,"total":10228,"name":"Benzie, Michigan","coordinates":[-86.49432,44.64862]}, {"dem":3500,"rep":6030,"total":10226,"name":"Adair, Missouri","coordinates":[-92.60359,40.19066]}, {"dem":1726,"rep":8163,"total":10218,"name":"Bandera, Texas","coordinates":[-99.24828,29.75638]}, {"dem":1800,"rep":8138,"total":10217,"name":"Henderson, Tennessee","coordinates":[-88.38767,35.65399]}, {"dem":2572,"rep":7067,"total":10208,"name":"Clinton, Missouri","coordinates":[-94.3958,39.60872]}, {"dem":2291,"rep":7705,"total":10187,"name":"Randolph, Alabama","coordinates":[-85.46406,33.29647]}, {"dem":6910,"rep":3099,"total":10186,"name":"Hertford, North Carolina","coordinates":[-76.98161,36.36351]}, {"dem":2081,"rep":7654,"total":10186,"name":"Mason, West Virginia","coordinates":[-82.029,38.77091]}, {"dem":1061,"rep":6673,"total":10164,"name":"Sanpete, Utah","coordinates":[-111.57288,39.38253]}, {"dem":3770,"rep":5983,"total":10164,"name":"Adams, Wisconsin","coordinates":[-89.76722,43.97375]}, {"dem":3195,"rep":6350,"total":10159,"name":"Finney, Kansas","coordinates":[-100.73996,38.0498]}, {"dem":2498,"rep":6718,"total":10155,"name":"Stutsman, North Dakota","coordinates":[-98.95612,46.97222]}, {"dem":3787,"rep":5720,"total":10133,"name":"Jones, Iowa","coordinates":[-91.11691,42.12511]}, {"dem":3260,"rep":6436,"total":10132,"name":"Langlade, Wisconsin","coordinates":[-89.06772,45.26238]}, {"dem":2585,"rep":7286,"total":10117,"name":"Hart, Georgia","coordinates":[-82.96329,34.34873]}, {"dem":1581,"rep":8247,"total":10100,"name":"Scott, Virginia","coordinates":[-82.61362,36.71277]}, {"dem":5369,"rep":4598,"total":10070,"name":"Yazoo, Mississippi","coordinates":[-90.38792,32.76567]}, {"dem":3659,"rep":5660,"total":10066,"name":"Yates, New York","coordinates":[-77.10432,42.63823]}, {"dem":2570,"rep":6981,"total":10061,"name":"Audrain, Missouri","coordinates":[-91.84341,39.21448]}, {"dem":2590,"rep":6893,"total":10053,"name":"White, Indiana","coordinates":[-86.86429,40.75094]}, {"dem":2935,"rep":6380,"total":10048,"name":"Gage, Nebraska","coordinates":[-96.68345,40.25523]}, {"dem":4235,"rep":5569,"total":10042,"name":"East Feliciana, Louisiana","coordinates":[-91.04343,30.83978]}, {"dem":1848,"rep":7841,"total":10038,"name":"McNairy, Tennessee","coordinates":[-88.56373,35.17537]}, {"dem":4575,"rep":4876,"total":10021,"name":"Kent, Maryland","coordinates":[-76.12598,39.24127]}, {"dem":5722,"rep":4150,"total":10003,"name":"Clay, Mississippi","coordinates":[-88.78246,33.65967]}, {"dem":2260,"rep":7309,"total":9985,"name":"Meigs, Ohio","coordinates":[-82.02839,39.0898]}, {"dem":2861,"rep":6572,"total":9979,"name":"Spencer, Indiana","coordinates":[-87.01037,38.00969]}, {"dem":3689,"rep":5620,"total":9975,"name":"Fayette, Iowa","coordinates":[-91.84037,42.86412]}, {"dem":3196,"rep":6385,"total":9960,"name":"Yancey, North Carolina","coordinates":[-82.30395,35.88932]}, {"dem":1622,"rep":8012,"total":9949,"name":"Hardin, Tennessee","coordinates":[-88.18569,35.20189]}, {"dem":4321,"rep":5351,"total":9935,"name":"Ouachita, Arkansas","coordinates":[-92.87841,33.59116]}, {"dem":4196,"rep":5341,"total":9900,"name":"Somerset, Maryland","coordinates":[-75.85332,38.07445]}, {"dem":1027,"rep":8696,"total":9891,"name":"George, Mississippi","coordinates":[-88.64226,30.85543]}, {"dem":2067,"rep":7648,"total":9872,"name":"Prentiss, Mississippi","coordinates":[-88.52218,34.62056]}, {"dem":2357,"rep":7075,"total":9866,"name":"Henry, Missouri","coordinates":[-93.79262,38.38649]}, {"dem":2462,"rep":6855,"total":9853,"name":"Perry, Illinois","coordinates":[-89.36852,38.08438]}, {"dem":6144,"rep":3582,"total":9848,"name":"Northampton, North Carolina","coordinates":[-77.39835,36.42177]}, {"dem":6413,"rep":3214,"total":9842,"name":"Warren, North Carolina","coordinates":[-78.09989,36.3981]}, {"dem":4304,"rep":4946,"total":9833,"name":"Poweshiek, Iowa","coordinates":[-92.52288,41.68452]}, {"dem":1845,"rep":7671,"total":9825,"name":"White, Tennessee","coordinates":[-85.45578,35.92704]}, {"dem":1837,"rep":7686,"total":9815,"name":"Stephens, Georgia","coordinates":[-83.29021,34.55291]}, {"dem":1703,"rep":7879,"total":9787,"name":"Sabine, Louisiana","coordinates":[-93.55957,31.5604]}, {"dem":1117,"rep":8470,"total":9737,"name":"Itawamba, Mississippi","coordinates":[-88.36312,34.28107]}, {"dem":3134,"rep":5741,"total":9736,"name":"Asotin, Washington","coordinates":[-117.22778,46.18186]}, {"dem":1851,"rep":7282,"total":9722,"name":"Logan, Colorado","coordinates":[-103.09046,40.72809]}, {"dem":2076,"rep":6984,"total":9722,"name":"Sumner, Kansas","coordinates":[-97.49335,37.23666]}, {"dem":1720,"rep":7764,"total":9718,"name":"Bell, Kentucky","coordinates":[-83.68071,36.72892]}, {"dem":1824,"rep":7724,"total":9696,"name":"Crawford, Missouri","coordinates":[-91.31393,37.96656]}, {"dem":3459,"rep":5420,"total":9676,"name":"Plumas, California","coordinates":[-120.82437,39.99229]}, {"dem":2838,"rep":5967,"total":9653,"name":"Waseca, Minnesota","coordinates":[-93.58984,44.01845]}, {"dem":3301,"rep":5659,"total":9623,"name":"Yankton, South Dakota","coordinates":[-97.38836,43.0066]}, {"dem":2568,"rep":6625,"total":9613,"name":"Brooke, West Virginia","coordinates":[-80.57869,40.27264]}, {"dem":2924,"rep":5945,"total":9608,"name":"Greene, Virginia","coordinates":[-78.47016,38.29798]}, {"dem":3524,"rep":5990,"total":9599,"name":"Wayne, Mississippi","coordinates":[-88.67821,31.6425]}, {"dem":6725,"rep":2794,"total":9598,"name":"Sunflower, Mississippi","coordinates":[-90.59509,33.60552]}, {"dem":3157,"rep":6287,"total":9597,"name":"Richland, Louisiana","coordinates":[-91.74835,32.41315]}, {"dem":1819,"rep":7372,"total":9585,"name":"Fayette, Illinois","coordinates":[-89.01792,39.00112]}, {"dem":1250,"rep":8043,"total":9572,"name":"Johnson, Kentucky","coordinates":[-82.83012,37.84775]}, {"dem":2080,"rep":7025,"total":9566,"name":"LaGrange, Indiana","coordinates":[-85.42784,41.64246]}, {"dem":1865,"rep":7338,"total":9561,"name":"Lincoln, Kentucky","coordinates":[-84.65833,37.45717]}, {"dem":1910,"rep":7268,"total":9559,"name":"Grant, Kentucky","coordinates":[-84.62592,38.64916]}, {"dem":3485,"rep":5134,"total":9558,"name":"Del Norte, California","coordinates":[-124.00361,41.76395]}, {"dem":3972,"rep":5456,"total":9542,"name":"Pickens, Alabama","coordinates":[-88.09686,33.29679]}, {"dem":3599,"rep":5295,"total":9541,"name":"Cedar, Iowa","coordinates":[-91.13261,41.77236]}, {"dem":2194,"rep":7065,"total":9533,"name":"Grimes, Texas","coordinates":[-95.98808,30.54323]}, {"dem":2252,"rep":6839,"total":9530,"name":"Fayette, Indiana","coordinates":[-85.18503,39.63965]}, {"dem":4954,"rep":4125,"total":9529,"name":"Bayfield, Wisconsin","coordinates":[-91.17728,46.63419]}, {"dem":1921,"rep":7196,"total":9515,"name":"Spencer, Kentucky","coordinates":[-85.31717,38.02541]}, {"dem":2566,"rep":6717,"total":9514,"name":"Butts, Georgia","coordinates":[-83.95822,33.29035]}, {"dem":4716,"rep":4367,"total":9512,"name":"Kleberg, Texas","coordinates":[-97.66062,27.43873]}, {"dem":1370,"rep":7911,"total":9510,"name":"Mingo, West Virginia","coordinates":[-82.15898,37.72116]}, {"dem":1840,"rep":7251,"total":9491,"name":"Nicholas, West Virginia","coordinates":[-80.79751,38.29143]}, {"dem":2758,"rep":6544,"total":9488,"name":"Putnam, Georgia","coordinates":[-83.37178,33.32106]}, {"dem":4400,"rep":4889,"total":9485,"name":"Barnwell, South Carolina","coordinates":[-81.43422,33.26055]}, {"dem":2398,"rep":6589,"total":9484,"name":"Taylor, Wisconsin","coordinates":[-90.50485,45.21165]}, {"dem":2663,"rep":6559,"total":9475,"name":"Morgan, Georgia","coordinates":[-83.49943,33.59869]}, {"dem":3065,"rep":5788,"total":9470,"name":"Glenn, California","coordinates":[-122.40169,39.60254]}, {"dem":2980,"rep":5483,"total":9459,"name":"Jefferson, Oregon","coordinates":[-121.17863,44.64515]}, {"dem":2529,"rep":6380,"total":9458,"name":"Nodaway, Missouri","coordinates":[-94.88314,40.36113]}, {"dem":2756,"rep":6548,"total":9438,"name":"Newton, Mississippi","coordinates":[-89.11841,32.40197]}, {"dem":2597,"rep":6511,"total":9419,"name":"Titus, Texas","coordinates":[-94.96678,33.21459]}, {"dem":5128,"rep":3289,"total":9412,"name":"Gunnison, Colorado","coordinates":[-107.05687,38.67049]}, {"dem":2904,"rep":5779,"total":9404,"name":"Henry, Iowa","coordinates":[-91.54725,40.9848]}, {"dem":1627,"rep":7543,"total":9399,"name":"Lee, Virginia","coordinates":[-83.13011,36.70172]}, {"dem":2701,"rep":6213,"total":9388,"name":"Green Lake, Wisconsin","coordinates":[-88.97037,43.78024]}, {"dem":3595,"rep":4980,"total":9359,"name":"Park, Montana","coordinates":[-110.53276,45.42142]}, {"dem":4731,"rep":4491,"total":9351,"name":"Burke, Georgia","coordinates":[-82.00016,33.06018]}, {"dem":2420,"rep":6482,"total":9348,"name":"Caddo, Oklahoma","coordinates":[-98.38104,35.16792]}, {"dem":5778,"rep":3456,"total":9347,"name":"Bertie, North Carolina","coordinates":[-76.96236,36.05904]}, {"dem":2041,"rep":6729,"total":9330,"name":"Lincoln, Montana","coordinates":[-115.46318,48.55238]}, {"dem":2025,"rep":7213,"total":9312,"name":"Benton, Missouri","coordinates":[-93.28794,38.30103]}, {"dem":2152,"rep":6930,"total":9290,"name":"Taylor, Florida","coordinates":[-83.60948,30.0099]}, {"dem":1926,"rep":7048,"total":9282,"name":"Washington, Missouri","coordinates":[-90.89701,37.94261]}, {"dem":2789,"rep":5977,"total":9274,"name":"Saline, Missouri","coordinates":[-93.20416,39.13584]}, {"dem":4185,"rep":4919,"total":9273,"name":"Hardeman, Tennessee","coordinates":[-88.98869,35.21878]}, {"dem":3821,"rep":4907,"total":9272,"name":"Jackson, Wisconsin","coordinates":[-90.79951,44.32458]}, {"dem":3699,"rep":5432,"total":9268,"name":"McDuffie, Georgia","coordinates":[-82.47873,33.47962]}, {"dem":1721,"rep":7296,"total":9247,"name":"Buchanan, Virginia","coordinates":[-82.03815,37.26811]}, {"dem":2106,"rep":6867,"total":9245,"name":"Allen, Louisiana","coordinates":[-92.8196,30.65274]}, {"dem":2957,"rep":5694,"total":9241,"name":"Delaware, Iowa","coordinates":[-91.36676,42.47293]}, {"dem":1842,"rep":7240,"total":9235,"name":"Tippah, Mississippi","coordinates":[-88.91881,34.76361]}, {"dem":3134,"rep":5516,"total":9231,"name":"Aitkin, Minnesota","coordinates":[-93.41976,46.60244]}, {"dem":2489,"rep":6367,"total":9226,"name":"Starke, Indiana","coordinates":[-86.64463,41.28447]}, {"dem":1766,"rep":7005,"total":9218,"name":"Upshur, West Virginia","coordinates":[-80.2316,38.90253]}, {"dem":3804,"rep":5222,"total":9217,"name":"Meriwether, Georgia","coordinates":[-84.66705,33.02926]}, {"dem":3013,"rep":6053,"total":9213,"name":"Grady, Georgia","coordinates":[-84.24508,30.8759]}, {"dem":3764,"rep":4801,"total":9204,"name":"Waynesboro, Virginia","coordinates":[-78.90141,38.06715]}, {"dem":3098,"rep":5406,"total":9182,"name":"Piscataquis, Maine","coordinates":[-69.10223,45.91563]}, {"dem":2506,"rep":6514,"total":9162,"name":"Franklin, Louisiana","coordinates":[-91.67237,32.13907]}, {"dem":2760,"rep":5975,"total":9161,"name":"King William, Virginia","coordinates":[-77.09105,37.70826]}, {"dem":3284,"rep":5404,"total":9148,"name":"Washburn, Wisconsin","coordinates":[-91.79642,45.89248]}, {"dem":4591,"rep":4101,"total":9143,"name":"Prince Edward, Virginia","coordinates":[-78.43295,37.22488]}, {"dem":7566,"rep":1431,"total":9140,"name":"Macon, Alabama","coordinates":[-85.69288,32.38702]}, {"dem":2045,"rep":6665,"total":9140,"name":"Andrew, Missouri","coordinates":[-94.80355,39.98886]}, {"dem":2338,"rep":6615,"total":9138,"name":"Toombs, Georgia","coordinates":[-82.33062,32.11781]}, {"dem":1542,"rep":7293,"total":9134,"name":"Letcher, Kentucky","coordinates":[-82.86125,37.11853]}, {"dem":3237,"rep":5317,"total":9129,"name":"Clayton, Iowa","coordinates":[-91.32357,42.84098]}, {"dem":2139,"rep":6430,"total":9121,"name":"Hancock, Illinois","coordinates":[-91.1688,40.40131]}, {"dem":3504,"rep":5185,"total":9121,"name":"Sawyer, Wisconsin","coordinates":[-91.14713,45.86491]}, {"dem":2427,"rep":6091,"total":9112,"name":"Johnson, Arkansas","coordinates":[-93.46632,35.57335]}, {"dem":2642,"rep":6074,"total":9101,"name":"Scott, Indiana","coordinates":[-85.75189,38.67943]}, {"dem":1758,"rep":7179,"total":9086,"name":"Shelby, Texas","coordinates":[-94.14257,31.79013]}, {"dem":2093,"rep":6500,"total":9047,"name":"Paulding, Ohio","coordinates":[-84.58212,41.11894]}, {"dem":2645,"rep":5634,"total":9008,"name":"Piatt, Illinois","coordinates":[-88.59235,40.00903]}, {"dem":4724,"rep":3885,"total":9008,"name":"Hopewell, Virginia","coordinates":[-77.29894,37.291]}, {"dem":3867,"rep":4835,"total":8964,"name":"Uvalde, Texas","coordinates":[-99.76842,29.3503]}, {"dem":6378,"rep":2426,"total":8912,"name":"Coahoma, Mississippi","coordinates":[-90.60316,34.22866]}, {"dem":3084,"rep":5205,"total":8904,"name":"Iowa, Iowa","coordinates":[-92.05912,41.68391]}, {"dem":2331,"rep":5896,"total":8902,"name":"Lincoln, New Mexico","coordinates":[-105.4498,33.74084]}, {"dem":3140,"rep":5456,"total":8887,"name":"Columbia, Arkansas","coordinates":[-93.23284,33.22303]}, {"dem":3850,"rep":4910,"total":8881,"name":"Winston, Mississippi","coordinates":[-89.03739,33.07872]}, {"dem":3595,"rep":5035,"total":8878,"name":"Southampton, Virginia","coordinates":[-77.10381,36.72006]}, {"dem":3122,"rep":5185,"total":8877,"name":"Mariposa, California","coordinates":[-119.91286,37.57002]}, {"dem":1105,"rep":6779,"total":8875,"name":"Lincoln, Wyoming","coordinates":[-110.68296,42.22999]}, {"dem":3272,"rep":5477,"total":8872,"name":"Concordia, Louisiana","coordinates":[-91.62631,31.4698]}, {"dem":2101,"rep":6366,"total":8858,"name":"Hale, Texas","coordinates":[-101.82288,34.06843]}, {"dem":3199,"rep":5490,"total":8852,"name":"Greene, Georgia","coordinates":[-83.16661,33.57674]}, {"dem":3295,"rep":5174,"total":8848,"name":"Rowan, Kentucky","coordinates":[-83.42807,38.20426]}, {"dem":2280,"rep":6116,"total":8833,"name":"Kalkaska, Michigan","coordinates":[-85.08899,44.67888]}, {"dem":1181,"rep":7408,"total":8821,"name":"Grant, Louisiana","coordinates":[-92.56171,31.59778]}, {"dem":1768,"rep":6760,"total":8821,"name":"Morgan, Missouri","coordinates":[-92.87483,38.4208]}, {"dem":1874,"rep":6738,"total":8819,"name":"Bibb, Alabama","coordinates":[-87.12714,33.01589]}, {"dem":3276,"rep":5435,"total":8811,"name":"Covington, Mississippi","coordinates":[-89.54889,31.63333]}, {"dem":5170,"rep":3488,"total":8806,"name":"Hampton, South Carolina","coordinates":[-81.14382,32.77833]}, {"dem":2791,"rep":5569,"total":8803,"name":"Bourbon, Kentucky","coordinates":[-84.20986,38.20256]}, {"dem":1797,"rep":6218,"total":8779,"name":"Baker, Oregon","coordinates":[-117.69193,44.70342]}, {"dem":1960,"rep":6484,"total":8774,"name":"Breckinridge, Kentucky","coordinates":[-86.43291,37.77798]}, {"dem":3091,"rep":5050,"total":8772,"name":"Schuyler, New York","coordinates":[-76.9386,42.41977]}, {"dem":3196,"rep":4971,"total":8752,"name":"Tama, Iowa","coordinates":[-92.52941,42.07484]}, {"dem":2948,"rep":5412,"total":8743,"name":"Burnett, Wisconsin","coordinates":[-92.37573,45.86689]}, {"dem":1520,"rep":6908,"total":8740,"name":"Perry, Missouri","coordinates":[-89.80212,37.71112]}, {"dem":3726,"rep":4901,"total":8732,"name":"Butler, Alabama","coordinates":[-86.68196,31.75166]}, {"dem":1992,"rep":6277,"total":8728,"name":"Crawford, Illinois","coordinates":[-87.76061,39.00278]}, {"dem":1240,"rep":7278,"total":8725,"name":"Pike, Georgia","coordinates":[-84.38984,33.08122]}, {"dem":1770,"rep":6637,"total":8723,"name":"Howard, Texas","coordinates":[-101.43872,32.30342]}, {"dem":1507,"rep":6489,"total":8704,"name":"Payette, Idaho","coordinates":[-116.75023,44.00243]}, {"dem":1790,"rep":6504,"total":8683,"name":"Boone, West Virginia","coordinates":[-81.71353,38.02281]}, {"dem":2051,"rep":6364,"total":8664,"name":"Milam, Texas","coordinates":[-96.98439,30.79124]}, {"dem":1170,"rep":7347,"total":8661,"name":"Lavaca, Texas","coordinates":[-96.92363,29.38257]}, {"dem":695,"rep":6740,"total":8654,"name":"Sevier, Utah","coordinates":[-111.81192,38.74682]}, {"dem":1892,"rep":6273,"total":8643,"name":"Carroll, Indiana","coordinates":[-86.56514,40.58498]}, {"dem":2678,"rep":5360,"total":8636,"name":"Madison, Iowa","coordinates":[-94.01518,41.33062]}, {"dem":2136,"rep":5984,"total":8635,"name":"Dawson, Nebraska","coordinates":[-99.81515,40.86737]}, {"dem":2733,"rep":5299,"total":8632,"name":"Nobles, Minnesota","coordinates":[-95.76313,43.67768]}, {"dem":2005,"rep":6182,"total":8620,"name":"Cherokee, Kansas","coordinates":[-94.84569,37.16939]}, {"dem":2249,"rep":5877,"total":8617,"name":"Clay, Iowa","coordinates":[-95.14987,43.08122]}, {"dem":1580,"rep":6692,"total":8608,"name":"Hampshire, West Virginia","coordinates":[-78.61198,39.31213]}, {"dem":2543,"rep":5653,"total":8607,"name":"Kossuth, Iowa","coordinates":[-94.21398,43.21247]}, {"dem":885,"rep":7526,"total":8604,"name":"Montague, Texas","coordinates":[-97.72501,33.67835]}, {"dem":1707,"rep":6533,"total":8599,"name":"Vernon, Missouri","coordinates":[-94.34159,37.85019]}, {"dem":3358,"rep":4494,"total":8588,"name":"Grand, Colorado","coordinates":[-106.11083,40.11306]}, {"dem":3836,"rep":4448,"total":8574,"name":"Westmoreland, Virginia","coordinates":[-76.80393,38.10931]}, {"dem":2813,"rep":5526,"total":8564,"name":"Saluda, South Carolina","coordinates":[-81.7279,34.00527]}, {"dem":2113,"rep":6138,"total":8559,"name":"Sullivan, Indiana","coordinates":[-87.41584,39.08922]}, {"dem":1946,"rep":6153,"total":8557,"name":"Owen, Indiana","coordinates":[-86.83884,39.31733]}, {"dem":2857,"rep":5288,"total":8556,"name":"Montour, Pennsylvania","coordinates":[-76.66522,41.02928]}, {"dem":2402,"rep":5790,"total":8537,"name":"Union, Illinois","coordinates":[-89.24463,37.48565]}, {"dem":2374,"rep":6042,"total":8533,"name":"Washington, Alabama","coordinates":[-88.19756,31.40521]}, {"dem":2787,"rep":5254,"total":8533,"name":"Hardin, Iowa","coordinates":[-93.24166,42.3902]}, {"dem":3620,"rep":4404,"total":8526,"name":"Clark, Arkansas","coordinates":[-93.1762,34.05331]}, {"dem":3071,"rep":4807,"total":8525,"name":"Mercer, Illinois","coordinates":[-90.74176,41.2056]}, {"dem":1768,"rep":6454,"total":8525,"name":"Patrick, Virginia","coordinates":[-80.28641,36.66713]}, {"dem":1814,"rep":5816,"total":8522,"name":"Elmore, Idaho","coordinates":[-115.4712,43.39469]}, {"dem":853,"rep":7483,"total":8514,"name":"Holmes, Florida","coordinates":[-85.81593,30.862]}, {"dem":1987,"rep":6325,"total":8513,"name":"Colorado, Texas","coordinates":[-96.50893,29.59629]}, {"dem":3526,"rep":4851,"total":8505,"name":"Madison, Florida","coordinates":[-83.47041,30.44723]}, {"dem":1243,"rep":7054,"total":8502,"name":"Franklin, Georgia","coordinates":[-83.22753,34.37526]}, {"dem":3444,"rep":4744,"total":8485,"name":"Bee, Texas","coordinates":[-97.74258,28.41607]}, {"dem":4368,"rep":4038,"total":8475,"name":"Jasper, Mississippi","coordinates":[-89.11943,32.01698]}, {"dem":1202,"rep":6154,"total":8470,"name":"Uinta, Wyoming","coordinates":[-110.55894,41.28472]}, {"dem":2542,"rep":5496,"total":8469,"name":"Ste. Genevieve, Missouri","coordinates":[-90.16153,37.88584]}, {"dem":4200,"rep":4149,"total":8461,"name":"Washington, Georgia","coordinates":[-82.79811,32.97184]}, {"dem":2367,"rep":5681,"total":8457,"name":"Colonial Heights, Virginia","coordinates":[-77.3968,37.26168]}, {"dem":2943,"rep":4928,"total":8452,"name":"Otero, Colorado","coordinates":[-103.72125,37.88416]}, {"dem":3584,"rep":4782,"total":8449,"name":"Leake, Mississippi","coordinates":[-89.52224,32.76063]}, {"dem":1458,"rep":6740,"total":8420,"name":"Gilchrist, Florida","coordinates":[-82.7958,29.72345]}, {"dem":1960,"rep":6010,"total":8374,"name":"Fulton, Indiana","coordinates":[-86.265,41.05038]}, {"dem":999,"rep":7166,"total":8371,"name":"Tishomingo, Mississippi","coordinates":[-88.23606,34.73769]}, {"dem":1978,"rep":6205,"total":8353,"name":"Houston, Texas","coordinates":[-95.42159,31.32303]}, {"dem":2518,"rep":5213,"total":8337,"name":"Jefferson, Kansas","coordinates":[-95.37531,39.23964]}, {"dem":3689,"rep":4154,"total":8318,"name":"Nelson, Virginia","coordinates":[-78.88343,37.78907]}, {"dem":2020,"rep":6152,"total":8295,"name":"Worth, Georgia","coordinates":[-83.84995,31.55177]}, {"dem":2856,"rep":4903,"total":8278,"name":"Buena Vista, Iowa","coordinates":[-95.14143,42.74152]}, {"dem":1048,"rep":6967,"total":8261,"name":"Wayne, Illinois","coordinates":[-88.43243,38.43185]}, {"dem":3242,"rep":4897,"total":8256,"name":"Attala, Mississippi","coordinates":[-89.58862,33.09046]}, {"dem":1613,"rep":6462,"total":8252,"name":"Chattooga, Georgia","coordinates":[-85.34528,34.47417]}, {"dem":1362,"rep":6712,"total":8249,"name":"Fayette, Alabama","coordinates":[-87.76429,33.71615]}, {"dem":1689,"rep":6298,"total":8249,"name":"Avery, North Carolina","coordinates":[-81.92028,36.07209]}, {"dem":1329,"rep":6599,"total":8242,"name":"McDonald, Missouri","coordinates":[-94.34395,36.63021]}, {"dem":1196,"rep":6441,"total":8233,"name":"Idaho, Idaho","coordinates":[-115.46733,45.84964]}, {"dem":1323,"rep":6637,"total":8233,"name":"Adair, Kentucky","coordinates":[-85.28137,37.10555]}, {"dem":1212,"rep":6618,"total":8231,"name":"Polk, Arkansas","coordinates":[-94.23088,34.49091]}, {"dem":1945,"rep":6059,"total":8229,"name":"Overton, Tennessee","coordinates":[-85.28307,36.34485]}, {"dem":3051,"rep":4661,"total":8213,"name":"Clarke, Virginia","coordinates":[-77.99074,39.1153]}, {"dem":1950,"rep":5910,"total":8212,"name":"Giles, Virginia","coordinates":[-80.69832,37.31807]}, {"dem":1609,"rep":6029,"total":8210,"name":"Dickinson, Kansas","coordinates":[-97.15794,38.86773]}, {"dem":1483,"rep":6385,"total":8205,"name":"Lampasas, Texas","coordinates":[-98.24088,31.19673]}, {"dem":2048,"rep":5803,"total":8192,"name":"Orange, Indiana","coordinates":[-86.48925,38.54738]}, {"dem":1036,"rep":5949,"total":8178,"name":"Cassia, Idaho","coordinates":[-113.62632,42.28231]}, {"dem":2327,"rep":5230,"total":8177,"name":"Kanabec, Minnesota","coordinates":[-93.29778,45.94775]}, {"dem":2450,"rep":5174,"total":8175,"name":"Hughes, South Dakota","coordinates":[-99.97568,44.38445]}, {"dem":1093,"rep":6863,"total":8174,"name":"Russell, Kentucky","coordinates":[-85.05495,36.99058]}, {"dem":1949,"rep":5698,"total":8169,"name":"Douglas, Illinois","coordinates":[-88.22286,39.76607]}, {"dem":3710,"rep":3748,"total":8156,"name":"Jefferson, Iowa","coordinates":[-91.96663,41.00588]}, {"dem":5199,"rep":2803,"total":8156,"name":"Lee, South Carolina","coordinates":[-80.2512,34.15864]}, {"dem":854,"rep":7042,"total":8155,"name":"Hutchinson, Texas","coordinates":[-101.36274,35.83704]}, {"dem":1170,"rep":6707,"total":8119,"name":"Wright, Missouri","coordinates":[-92.47998,37.26763]}, {"dem":2679,"rep":5122,"total":8111,"name":"Marion, Kentucky","coordinates":[-85.26895,37.5526]}, {"dem":2291,"rep":5335,"total":8107,"name":"Labette, Kansas","coordinates":[-95.29747,37.19146]}, {"dem":1349,"rep":6466,"total":8096,"name":"Allen, Kentucky","coordinates":[-86.19245,36.75077]}, {"dem":1596,"rep":6282,"total":8096,"name":"Mitchell, North Carolina","coordinates":[-82.16355,36.0131]}, {"dem":3605,"rep":4374,"total":8095,"name":"Greene, North Carolina","coordinates":[-77.68168,35.48195]}, {"dem":3056,"rep":4884,"total":8087,"name":"Lauderdale, Tennessee","coordinates":[-89.62773,35.76295]}, {"dem":3155,"rep":4248,"total":8086,"name":"Inyo, California","coordinates":[-117.40392,36.56197]}, {"dem":2408,"rep":5338,"total":8083,"name":"Ashley, Arkansas","coordinates":[-91.77226,33.19083]}, {"dem":6689,"rep":1309,"total":8076,"name":"Holmes, Mississippi","coordinates":[-90.09119,33.12594]}, {"dem":2292,"rep":5632,"total":8072,"name":"Henry, Alabama","coordinates":[-85.23997,31.51697]}, {"dem":3741,"rep":3195,"total":8063,"name":"Cibola, New Mexico","coordinates":[-107.99268,34.92827]}, {"dem":3179,"rep":4375,"total":8060,"name":"Floyd, Iowa","coordinates":[-92.78736,43.05274]}, {"dem":3062,"rep":4556,"total":8055,"name":"Perry, Indiana","coordinates":[-86.62653,38.08143]}, {"dem":3577,"rep":4023,"total":8055,"name":"Richland, Wisconsin","coordinates":[-90.43569,43.37619]}, {"dem":2300,"rep":5293,"total":8051,"name":"Floyd, Virginia","coordinates":[-80.35026,36.93143]}, {"dem":4775,"rep":3173,"total":8040,"name":"Hale, Alabama","coordinates":[-87.62306,32.75279]}, {"dem":2071,"rep":5613,"total":8037,"name":"Seminole, Oklahoma","coordinates":[-96.60285,35.15836]}, {"dem":4228,"rep":3302,"total":8029,"name":"Ashland, Wisconsin","coordinates":[-90.67969,46.54442]}, {"dem":1618,"rep":6001,"total":8023,"name":"Bates, Missouri","coordinates":[-94.33924,38.25721]}, {"dem":1248,"rep":6624,"total":8016,"name":"Tyler, Texas","coordinates":[-94.37565,30.76929]}, {"dem":2023,"rep":5715,"total":8011,"name":"Appomattox, Virginia","coordinates":[-78.81094,37.37072]}, {"dem":1154,"rep":6626,"total":8008,"name":"Grainger, Tennessee","coordinates":[-83.50954,36.2775]}, {"dem":1444,"rep":6287,"total":7992,"name":"Rabun, Georgia","coordinates":[-83.40487,34.88393]}, {"dem":1431,"rep":6371,"total":7992,"name":"Wayne, Kentucky","coordinates":[-84.82658,36.80077]}, {"dem":2539,"rep":5292,"total":7987,"name":"Elbert, Georgia","coordinates":[-82.8419,34.11641]}, {"dem":1889,"rep":5697,"total":7986,"name":"Jay, Indiana","coordinates":[-85.00233,40.43495]}, {"dem":1932,"rep":5624,"total":7986,"name":"Cooper, Missouri","coordinates":[-92.81232,38.84538]}, {"dem":2123,"rep":5505,"total":7963,"name":"McIntosh, Oklahoma","coordinates":[-95.67178,35.3691]}, {"dem":1229,"rep":5980,"total":7954,"name":"Gem, Idaho","coordinates":[-116.39878,44.06147]}, {"dem":2355,"rep":5157,"total":7952,"name":"Davison, South Dakota","coordinates":[-98.15586,43.68043]}, {"dem":1717,"rep":5275,"total":7952,"name":"Carbon, Utah","coordinates":[-110.58848,39.67328]}, {"dem":2518,"rep":5016,"total":7945,"name":"Brown, Indiana","coordinates":[-86.23012,39.19511]}, {"dem":1877,"rep":5622,"total":7928,"name":"Clark, Illinois","coordinates":[-87.79168,39.33233]}, {"dem":2656,"rep":4849,"total":7927,"name":"Conway, Arkansas","coordinates":[-92.68924,35.2657]}, {"dem":1875,"rep":5454,"total":7922,"name":"Seward, Nebraska","coordinates":[-97.14038,40.87194]}, {"dem":1715,"rep":5746,"total":7921,"name":"Logan, Arkansas","coordinates":[-93.72091,35.21865]}, {"dem":2227,"rep":5290,"total":7897,"name":"Union, South Dakota","coordinates":[-96.65082,42.8311]}, {"dem":2809,"rep":4714,"total":7893,"name":"Marquette, Wisconsin","coordinates":[-89.40909,43.82605]}, {"dem":3649,"rep":4127,"total":7890,"name":"Chickasaw, Mississippi","coordinates":[-88.94755,33.93327]}, {"dem":3493,"rep":4279,"total":7880,"name":"Mitchell, Georgia","coordinates":[-84.19203,31.22899]}, {"dem":1793,"rep":5645,"total":7873,"name":"Edgar, Illinois","coordinates":[-87.74711,39.67903]}, {"dem":2435,"rep":5335,"total":7860,"name":"Emanuel, Georgia","coordinates":[-82.29976,32.59109]}, {"dem":1278,"rep":6339,"total":7838,"name":"Bosque, Texas","coordinates":[-97.63764,31.90081]}, {"dem":1062,"rep":6547,"total":7831,"name":"Wyoming, West Virginia","coordinates":[-81.54903,37.60366]}, {"dem":1824,"rep":5695,"total":7813,"name":"Hickman, Tennessee","coordinates":[-87.46711,35.80232]}, {"dem":2987,"rep":4275,"total":7807,"name":"Warren, Illinois","coordinates":[-90.62022,40.85044]}, {"dem":1473,"rep":5969,"total":7806,"name":"Jackson, Oklahoma","coordinates":[-99.41223,34.594]}, {"dem":1856,"rep":5451,"total":7804,"name":"Roseau, Minnesota","coordinates":[-95.8215,48.76106]}, {"dem":2585,"rep":5137,"total":7791,"name":"Clarke, Mississippi","coordinates":[-88.68797,32.04537]}, {"dem":1302,"rep":6251,"total":7784,"name":"Potter, Pennsylvania","coordinates":[-77.89443,41.74858]}, {"dem":2031,"rep":5435,"total":7781,"name":"Harrison, Kentucky","coordinates":[-84.33413,38.44457]}, {"dem":1954,"rep":5193,"total":7774,"name":"Sibley, Minnesota","coordinates":[-94.23012,44.57573]}, {"dem":5819,"rep":1324,"total":7757,"name":"Falls Church, Virginia","coordinates":[-77.1756,38.88472]}, {"dem":3425,"rep":3844,"total":7744,"name":"Crawford, Wisconsin","coordinates":[-90.95123,43.24991]}, {"dem":1778,"rep":5796,"total":7739,"name":"Limestone, Texas","coordinates":[-96.59362,31.54754]}, {"dem":1880,"rep":5502,"total":7722,"name":"Poinsett, Arkansas","coordinates":[-90.6811,35.56887]}, {"dem":2149,"rep":5114,"total":7718,"name":"Ford, Kansas","coordinates":[-99.88474,37.68841]}, {"dem":876,"rep":6601,"total":7707,"name":"Young, Texas","coordinates":[-98.67838,33.15877]}, {"dem":2090,"rep":5067,"total":7698,"name":"Mills, Iowa","coordinates":[-95.6191,41.0337]}, {"dem":2384,"rep":4950,"total":7696,"name":"Arenac, Michigan","coordinates":[-83.74067,44.03683]}, {"dem":2726,"rep":4463,"total":7694,"name":"Hamilton, Iowa","coordinates":[-93.70919,42.39076]}, {"dem":1584,"rep":5739,"total":7684,"name":"Richland, Illinois","coordinates":[-88.08545,38.71218]}, {"dem":1471,"rep":6026,"total":7684,"name":"Freestone, Texas","coordinates":[-96.14495,31.70174]}, {"dem":4481,"rep":3046,"total":7669,"name":"Brunswick, Virginia","coordinates":[-77.86148,36.7642]}, {"dem":3288,"rep":3977,"total":7662,"name":"Lafayette, Wisconsin","coordinates":[-90.13029,42.65557]}, {"dem":1573,"rep":5732,"total":7654,"name":"Morgan, West Virginia","coordinates":[-78.25734,39.555]}, {"dem":3541,"rep":3930,"total":7645,"name":"Jefferson, Florida","coordinates":[-83.89085,30.42455]}, {"dem":1617,"rep":5928,"total":7627,"name":"Smith, Mississippi","coordinates":[-89.49487,32.01902]}, {"dem":5206,"rep":1925,"total":7626,"name":"Williamsburg, Virginia","coordinates":[-76.70819,37.26948]}, {"dem":1453,"rep":5904,"total":7623,"name":"Garrard, Kentucky","coordinates":[-84.54585,37.63016]}, {"dem":1548,"rep":5798,"total":7621,"name":"Macon, Missouri","coordinates":[-92.56434,39.82979]}, {"dem":2270,"rep":5190,"total":7612,"name":"Lamar, Georgia","coordinates":[-84.14668,33.07444]}, {"dem":1887,"rep":5137,"total":7611,"name":"Redwood, Minnesota","coordinates":[-95.25424,44.40353]}, {"dem":2117,"rep":4890,"total":7606,"name":"Renville, Minnesota","coordinates":[-94.95561,44.72369]}, {"dem":873,"rep":6347,"total":7595,"name":"Woodward, Oklahoma","coordinates":[-99.27366,36.42561]}, {"dem":2064,"rep":4767,"total":7592,"name":"Richland, North Dakota","coordinates":[-96.93795,46.26521]}, {"dem":2149,"rep":5242,"total":7583,"name":"Hardee, Florida","coordinates":[-81.82157,27.49284]}, {"dem":2669,"rep":4562,"total":7577,"name":"Price, Wisconsin","coordinates":[-90.35964,45.67907]}, {"dem":960,"rep":6308,"total":7552,"name":"Beckham, Oklahoma","coordinates":[-99.69005,35.2706]}, {"dem":3573,"rep":3787,"total":7549,"name":"Calhoun, South Carolina","coordinates":[-80.78034,33.67478]}, {"dem":1910,"rep":5077,"total":7543,"name":"De Witt, Illinois","coordinates":[-88.90185,40.18149]}, {"dem":2144,"rep":5077,"total":7531,"name":"Simpson, Kentucky","coordinates":[-86.58179,36.74093]}, {"dem":1413,"rep":5754,"total":7530,"name":"Pike, Illinois","coordinates":[-90.88903,39.6251]}, {"dem":2068,"rep":4888,"total":7530,"name":"Bond, Illinois","coordinates":[-89.43659,38.88592]}, {"dem":2157,"rep":4921,"total":7513,"name":"Butler, Iowa","coordinates":[-92.78015,42.73475]}, {"dem":2837,"rep":4549,"total":7512,"name":"Crisp, Georgia","coordinates":[-83.75353,31.91514]}, {"dem":1587,"rep":5589,"total":7510,"name":"Tipton, Indiana","coordinates":[-86.0562,40.31022]}, {"dem":2722,"rep":4274,"total":7504,"name":"Geary, Kansas","coordinates":[-96.76809,39.00213]}, {"dem":1072,"rep":6263,"total":7504,"name":"Macon, Tennessee","coordinates":[-86.00095,36.53775]}, {"dem":1476,"rep":5662,"total":7492,"name":"Fountain, Indiana","coordinates":[-87.23487,40.12123]}, {"dem":2131,"rep":4902,"total":7465,"name":"Harrison, Iowa","coordinates":[-95.82714,41.68858]}, {"dem":2139,"rep":5169,"total":7464,"name":"Jackson, Louisiana","coordinates":[-92.56169,32.30429]}, {"dem":2025,"rep":4860,"total":7457,"name":"Otoe, Nebraska","coordinates":[-96.13102,40.63799]}, {"dem":1272,"rep":5895,"total":7453,"name":"Dallas, Missouri","coordinates":[-93.03381,37.68358]}, {"dem":1373,"rep":5725,"total":7445,"name":"Grant, Arkansas","coordinates":[-92.42297,34.28556]}, {"dem":2447,"rep":4434,"total":7445,"name":"Carroll, Illinois","coordinates":[-89.92418,42.0709]}, {"dem":1520,"rep":5670,"total":7445,"name":"Gasconade, Missouri","coordinates":[-91.50577,38.44118]}, {"dem":909,"rep":6391,"total":7439,"name":"Leon, Texas","coordinates":[-95.99562,31.30049]}, {"dem":3294,"rep":3203,"total":7436,"name":"District 16, Alaska","coordinates":[179.62118,51.94896]}, {"dem":1689,"rep":5494,"total":7436,"name":"Smith, Tennessee","coordinates":[-85.94191,36.25664]}, {"dem":4031,"rep":3195,"total":7430,"name":"St. Francis, Arkansas","coordinates":[-90.7515,35.02283]}, {"dem":1448,"rep":5571,"total":7427,"name":"Washington, Illinois","coordinates":[-89.41718,38.35314]}, {"dem":2153,"rep":4659,"total":7412,"name":"Faribault, Minnesota","coordinates":[-93.94723,43.67652]}, {"dem":1315,"rep":5752,"total":7406,"name":"O'Brien, Iowa","coordinates":[-95.62562,43.08374]}, {"dem":701,"rep":6500,"total":7405,"name":"Gray, Texas","coordinates":[-100.81237,35.40254]}, {"dem":2852,"rep":4302,"total":7398,"name":"Northumberland, Virginia","coordinates":[-76.37968,37.85697]}, {"dem":1806,"rep":5274,"total":7382,"name":"Pike, Missouri","coordinates":[-91.1716,39.33995]}, {"dem":1933,"rep":5270,"total":7357,"name":"New Madrid, Missouri","coordinates":[-89.65594,36.59426]}, {"dem":1549,"rep":5382,"total":7339,"name":"Van Buren, Arkansas","coordinates":[-92.51597,35.58295]}, {"dem":2500,"rep":4264,"total":7339,"name":"Archuleta, Colorado","coordinates":[-107.05086,37.20239]}, {"dem":1412,"rep":5640,"total":7335,"name":"White, Illinois","coordinates":[-88.17862,38.08732]}, {"dem":1100,"rep":6038,"total":7333,"name":"Fentress, Tennessee","coordinates":[-84.93776,36.36989]}, {"dem":2925,"rep":4018,"total":7329,"name":"Gogebic, Michigan","coordinates":[-89.80686,46.46151]}, {"dem":2166,"rep":4874,"total":7325,"name":"Alleghany, Virginia","coordinates":[-80.00866,37.7879]}, {"dem":1565,"rep":5386,"total":7317,"name":"Missaukee, Michigan","coordinates":[-85.08547,44.32542]}, {"dem":903,"rep":6302,"total":7311,"name":"Pierce, Georgia","coordinates":[-82.21037,31.35399]}, {"dem":1260,"rep":5809,"total":7311,"name":"Hockley, Texas","coordinates":[-102.34339,33.60593]}, {"dem":3195,"rep":3478,"total":7295,"name":"Luna, New Mexico","coordinates":[-107.74719,32.18452]}, {"dem":3128,"rep":3950,"total":7295,"name":"Buckingham, Virginia","coordinates":[-78.52916,37.57392]}, {"dem":1720,"rep":5329,"total":7293,"name":"Gulf, Florida","coordinates":[-85.25653,29.90725]}, {"dem":3109,"rep":4106,"total":7292,"name":"Choctaw, Alabama","coordinates":[-88.24888,31.99095]}, {"dem":1407,"rep":5592,"total":7285,"name":"Grayson, Virginia","coordinates":[-81.21532,36.65222]}, {"dem":1730,"rep":5320,"total":7264,"name":"Hart, Kentucky","coordinates":[-85.88212,37.30909]}, {"dem":1472,"rep":5407,"total":7249,"name":"Sharp, Arkansas","coordinates":[-91.47106,36.17339]}, {"dem":2992,"rep":4014,"total":7228,"name":"Chowan, North Carolina","coordinates":[-76.60275,36.12897]}, {"dem":1970,"rep":4944,"total":7219,"name":"Mason, Kentucky","coordinates":[-83.82812,38.59413]}, {"dem":2400,"rep":4488,"total":7218,"name":"Presque Isle, Michigan","coordinates":[-83.38401,45.48951]}, {"dem":1525,"rep":5292,"total":7214,"name":"Rush, Indiana","coordinates":[-85.46644,39.62237]}, {"dem":1270,"rep":5822,"total":7202,"name":"Dixie, Florida","coordinates":[-83.19566,29.58089]}, {"dem":1262,"rep":5671,"total":7195,"name":"Unicoi, Tennessee","coordinates":[-82.41821,36.10012]}, {"dem":1601,"rep":5092,"total":7177,"name":"Poquoson, Virginia","coordinates":[-76.30353,37.12835]}, {"dem":1967,"rep":4930,"total":7153,"name":"Humphreys, Tennessee","coordinates":[-87.79045,36.04082]}, {"dem":1828,"rep":4944,"total":7149,"name":"Henry, Kentucky","coordinates":[-85.11964,38.45138]}, {"dem":4151,"rep":2187,"total":7140,"name":"District 20, Alaska","coordinates":[-149.28432,61.17425]}, {"dem":1951,"rep":4761,"total":7125,"name":"Cass, Iowa","coordinates":[-94.9333,41.33382]}, {"dem":934,"rep":6044,"total":7123,"name":"Scott, Tennessee","coordinates":[-84.50352,36.43523]}, {"dem":1434,"rep":5336,"total":7107,"name":"Marion, Arkansas","coordinates":[-92.67857,36.26666]}, {"dem":998,"rep":5856,"total":7090,"name":"Osage, Missouri","coordinates":[-91.8595,38.46425]}, {"dem":2171,"rep":4564,"total":7087,"name":"Rusk, Wisconsin","coordinates":[-91.13674,45.47273]}, {"dem":1688,"rep":5098,"total":7079,"name":"Harrison, Ohio","coordinates":[-81.09156,40.29231]}, {"dem":1459,"rep":5307,"total":7066,"name":"Lincoln, West Virginia","coordinates":[-82.07762,38.17176]}, {"dem":2697,"rep":4289,"total":7050,"name":"Amite, Mississippi","coordinates":[-90.79554,31.20393]}, {"dem":2377,"rep":4401,"total":7049,"name":"Hempstead, Arkansas","coordinates":[-93.66435,33.73595]}, {"dem":1753,"rep":4826,"total":7046,"name":"Osage, Kansas","coordinates":[-95.70825,38.65021]}, {"dem":1573,"rep":5306,"total":7045,"name":"Stone, Mississippi","coordinates":[-89.11229,30.79018]}, {"dem":1807,"rep":4893,"total":7044,"name":"Page, Iowa","coordinates":[-95.14428,40.73909]}, {"dem":2128,"rep":4708,"total":7040,"name":"Amelia, Virginia","coordinates":[-77.97746,37.33192]}, {"dem":2203,"rep":4668,"total":7035,"name":"Robertson, Texas","coordinates":[-96.51494,31.02548]}, {"dem":1835,"rep":4892,"total":7032,"name":"Bristol, Virginia","coordinates":[-82.15756,36.61695]}, {"dem":1434,"rep":5494,"total":7012,"name":"Appling, Georgia","coordinates":[-82.2901,31.73971]}, {"dem":1839,"rep":5021,"total":7009,"name":"Dodge, Georgia","coordinates":[-83.16786,32.16436]}, {"dem":3129,"rep":3756,"total":7005,"name":"Bienville, Louisiana","coordinates":[-93.04115,32.34095]}, {"dem":2531,"rep":4049,"total":6988,"name":"Buffalo, Wisconsin","coordinates":[-91.76129,44.38563]}, {"dem":2203,"rep":4419,"total":6979,"name":"Madison, Virginia","coordinates":[-78.27696,38.41205]}, {"dem":684,"rep":6134,"total":6975,"name":"Banks, Georgia","coordinates":[-83.49844,34.35192]}, {"dem":3821,"rep":3063,"total":6968,"name":"Jefferson, Georgia","coordinates":[-82.42,33.05817]}, {"dem":1036,"rep":5823,"total":6966,"name":"Lamar, Alabama","coordinates":[-88.08743,33.78708]}, {"dem":2118,"rep":4638,"total":6965,"name":"Calhoun, Texas","coordinates":[-96.57957,28.44171]}, {"dem":776,"rep":6011,"total":6963,"name":"Eastland, Texas","coordinates":[-98.83655,32.32464]}, {"dem":1491,"rep":5316,"total":6960,"name":"Burleson, Texas","coordinates":[-96.62209,30.49348]}, {"dem":1569,"rep":5171,"total":6955,"name":"DeKalb, Tennessee","coordinates":[-85.83359,35.98221]}, {"dem":4310,"rep":2446,"total":6953,"name":"Phillips, Arkansas","coordinates":[-90.85559,34.42368]}, {"dem":500,"rep":5508,"total":6942,"name":"Duchesne, Utah","coordinates":[-110.42958,40.28939]}, {"dem":3189,"rep":3046,"total":6939,"name":"Alamosa, Colorado","coordinates":[-105.78804,37.56844]}, {"dem":2081,"rep":4513,"total":6939,"name":"Vermillion, Indiana","coordinates":[-87.46207,39.85404]}, {"dem":1991,"rep":4617,"total":6935,"name":"Crawford, Iowa","coordinates":[-95.38909,42.04311]}, {"dem":1684,"rep":4837,"total":6934,"name":"Wadena, Minnesota","coordinates":[-94.9886,46.58698]}, {"dem":1347,"rep":5274,"total":6928,"name":"Lewis, West Virginia","coordinates":[-80.49547,38.98887]}, {"dem":2421,"rep":4093,"total":6923,"name":"Allamakee, Iowa","coordinates":[-91.38275,43.27496]}, {"dem":2790,"rep":4056,"total":6919,"name":"Walthall, Mississippi","coordinates":[-90.10343,31.16449]}, {"dem":1681,"rep":5096,"total":6903,"name":"Tattnall, Georgia","coordinates":[-82.0592,32.04376]}, {"dem":1999,"rep":4584,"total":6874,"name":"Cross, Arkansas","coordinates":[-90.76398,35.28569]}, {"dem":1856,"rep":4527,"total":6872,"name":"Grundy, Iowa","coordinates":[-92.79024,42.40333]}, {"dem":1167,"rep":4887,"total":6871,"name":"Minidoka, Idaho","coordinates":[-113.63984,42.85721]}, {"dem":2448,"rep":4258,"total":6870,"name":"Pamlico, North Carolina","coordinates":[-76.66526,35.14757]}, {"dem":3313,"rep":2616,"total":6868,"name":"Socorro, New Mexico","coordinates":[-106.93913,33.99165]}, {"dem":2110,"rep":4354,"total":6844,"name":"Crawford, Michigan","coordinates":[-84.61134,44.68017]}, {"dem":1163,"rep":5519,"total":6844,"name":"Dewitt, Texas","coordinates":[-97.36165,29.08234]}, {"dem":1588,"rep":4928,"total":6841,"name":"Madison, Arkansas","coordinates":[-93.72405,36.01254]}, {"dem":3711,"rep":3013,"total":6834,"name":"Haywood, Tennessee","coordinates":[-89.28269,35.58667]}, {"dem":1237,"rep":5347,"total":6830,"name":"Moniteau, Missouri","coordinates":[-92.58364,38.63303]}, {"dem":1934,"rep":4373,"total":6802,"name":"Pend Oreille, Washington","coordinates":[-117.23219,48.54382]}, {"dem":1662,"rep":4868,"total":6795,"name":"Monroe, Ohio","coordinates":[-81.09098,39.72625]}, {"dem":2650,"rep":3710,"total":6793,"name":"Las Animas, Colorado","coordinates":[-104.04411,37.31883]}, {"dem":978,"rep":5600,"total":6791,"name":"Dent, Missouri","coordinates":[-91.48971,37.60307]}, {"dem":2314,"rep":4038,"total":6786,"name":"Lake, South Dakota","coordinates":[-97.12322,44.02844]}, {"dem":1912,"rep":4455,"total":6772,"name":"Beadle, South Dakota","coordinates":[-98.27942,44.41826]}, {"dem":912,"rep":5694,"total":6771,"name":"Fulton, Pennsylvania","coordinates":[-78.12261,39.91075]}, {"dem":1376,"rep":5039,"total":6770,"name":"Franklin, Arkansas","coordinates":[-93.88766,35.50855]}, {"dem":752,"rep":5861,"total":6767,"name":"Clay, Kentucky","coordinates":[-83.71547,37.16427]}, {"dem":1210,"rep":5383,"total":6764,"name":"Towns, Georgia","coordinates":[-83.73226,34.90252]}, {"dem":1329,"rep":4644,"total":6751,"name":"Jerome, Idaho","coordinates":[-114.26208,42.69139]}, {"dem":1587,"rep":4931,"total":6751,"name":"Trigg, Kentucky","coordinates":[-87.85865,36.80768]}, {"dem":2829,"rep":3712,"total":6744,"name":"Nottoway, Virginia","coordinates":[-78.05386,37.14116]}, {"dem":2147,"rep":4000,"total":6715,"name":"Pennington, Minnesota","coordinates":[-96.03772,48.06924]}, {"dem":1998,"rep":4177,"total":6714,"name":"Jefferson, Montana","coordinates":[-112.05942,46.12423]}, {"dem":2319,"rep":4177,"total":6708,"name":"Perquimans, North Carolina","coordinates":[-76.40324,36.18089]}, {"dem":1054,"rep":5441,"total":6705,"name":"Morgan, Tennessee","coordinates":[-84.63926,36.13869]}, {"dem":915,"rep":5609,"total":6691,"name":"Rockcastle, Kentucky","coordinates":[-84.31436,37.36105]}, {"dem":4883,"rep":1751,"total":6684,"name":"Lowndes, Alabama","coordinates":[-86.65058,32.14788]}, {"dem":1558,"rep":4846,"total":6683,"name":"Massac, Illinois","coordinates":[-88.70565,37.21611]}, {"dem":1831,"rep":4625,"total":6674,"name":"Oglethorpe, Georgia","coordinates":[-83.07408,33.8668]}, {"dem":984,"rep":5486,"total":6666,"name":"Douglas, Missouri","coordinates":[-92.51589,36.94651]}, {"dem":668,"rep":5520,"total":6654,"name":"Converse, Wyoming","coordinates":[-105.52475,42.98462]}, {"dem":2869,"rep":3523,"total":6645,"name":"Lancaster, Virginia","coordinates":[-76.41266,37.70484]}, {"dem":2661,"rep":3551,"total":6632,"name":"Colusa, California","coordinates":[-122.23756,39.17773]}, {"dem":1237,"rep":5245,"total":6624,"name":"Clay, Alabama","coordinates":[-85.86352,33.27039]}, {"dem":2365,"rep":3968,"total":6595,"name":"Drew, Arkansas","coordinates":[-91.72277,33.58724]}, {"dem":684,"rep":5764,"total":6593,"name":"Cleburne, Alabama","coordinates":[-85.51612,33.67196]}, {"dem":1047,"rep":5422,"total":6590,"name":"Berrien, Georgia","coordinates":[-83.22786,31.28865]}, {"dem":3080,"rep":3420,"total":6585,"name":"Conecuh, Alabama","coordinates":[-86.98872,31.43092]}, {"dem":1441,"rep":4863,"total":6582,"name":"Parke, Indiana","coordinates":[-87.19695,39.77424]}, {"dem":988,"rep":5410,"total":6579,"name":"Johnson, Tennessee","coordinates":[-81.86124,36.4532]}, {"dem":1989,"rep":4049,"total":6575,"name":"Atchison, Kansas","coordinates":[-95.31339,39.53254]}, {"dem":605,"rep":5836,"total":6569,"name":"La Salle, Louisiana","coordinates":[-92.16159,31.68008]}, {"dem":1491,"rep":4733,"total":6538,"name":"Taylor, West Virginia","coordinates":[-80.04655,39.33247]}, {"dem":1372,"rep":4997,"total":6535,"name":"Lee, Texas","coordinates":[-96.97682,30.32149]}, {"dem":1684,"rep":4028,"total":6533,"name":"District 13, Alaska","coordinates":[-161.99747,55.24504]}, {"dem":874,"rep":5305,"total":6525,"name":"Moffat, Colorado","coordinates":[-108.21715,40.61086]}, {"dem":3077,"rep":2932,"total":6521,"name":"Lake, Minnesota","coordinates":[-91.4117,47.51711]}, {"dem":1252,"rep":5097,"total":6520,"name":"Polk, Tennessee","coordinates":[-84.54111,35.10943]}, {"dem":1817,"rep":4231,"total":6515,"name":"Menard, Illinois","coordinates":[-89.79413,40.02256]}, {"dem":1382,"rep":4787,"total":6513,"name":"Adair, Oklahoma","coordinates":[-94.65102,35.89804]}, {"dem":1243,"rep":5081,"total":6507,"name":"Chester, Tennessee","coordinates":[-88.61135,35.42025]}, {"dem":2014,"rep":4058,"total":6486,"name":"Mason, Illinois","coordinates":[-89.91357,40.23699]}, {"dem":2371,"rep":3478,"total":6445,"name":"Hill, Montana","coordinates":[-110.10632,48.63195]}, {"dem":1736,"rep":4431,"total":6443,"name":"Morgan, Ohio","coordinates":[-81.86169,39.62494]}, {"dem":1335,"rep":4932,"total":6440,"name":"Dickenson, Virginia","coordinates":[-82.34921,37.1367]}, {"dem":1480,"rep":4608,"total":6439,"name":"Yell, Arkansas","coordinates":[-93.4083,34.99771]}, {"dem":767,"rep":5482,"total":6439,"name":"Casey, Kentucky","coordinates":[-84.92821,37.32196]}, {"dem":2266,"rep":3742,"total":6435,"name":"Chickasaw, Iowa","coordinates":[-92.31721,43.05974]}, {"dem":1386,"rep":4521,"total":6433,"name":"Humboldt, Nevada","coordinates":[-118.12759,41.40791]}, {"dem":2717,"rep":3585,"total":6421,"name":"Claiborne, Louisiana","coordinates":[-92.98972,32.82715]}, {"dem":1265,"rep":4879,"total":6421,"name":"Livingston, Missouri","coordinates":[-93.5482,39.77858]}, {"dem":4746,"rep":1581,"total":6411,"name":"Sumter, Alabama","coordinates":[-88.20005,32.59748]}, {"dem":4146,"rep":1892,"total":6406,"name":"Nantucket, Massachusetts","coordinates":[-70.1419,41.30587]}, {"dem":1414,"rep":4480,"total":6396,"name":"Ford, Illinois","coordinates":[-88.22458,40.59653]}, {"dem":1910,"rep":4390,"total":6396,"name":"Calhoun, Mississippi","coordinates":[-89.33711,33.93663]}, {"dem":1186,"rep":4700,"total":6381,"name":"York, Nebraska","coordinates":[-97.59674,40.87305]}, {"dem":1425,"rep":4509,"total":6379,"name":"Randolph, Arkansas","coordinates":[-91.02844,36.34129]}, {"dem":920,"rep":5192,"total":6377,"name":"Lyon, Iowa","coordinates":[-96.2072,43.38357]}, {"dem":1279,"rep":4409,"total":6374,"name":"Carbon, Wyoming","coordinates":[-106.93315,41.70359]}, {"dem":1644,"rep":4608,"total":6372,"name":"Winn, Louisiana","coordinates":[-92.64126,31.94118]}, {"dem":1662,"rep":4362,"total":6370,"name":"Shelby, Iowa","coordinates":[-95.30891,41.67901]}, {"dem":1278,"rep":4799,"total":6367,"name":"Larue, Kentucky","coordinates":[-85.69684,37.54446]}, {"dem":2195,"rep":4091,"total":6364,"name":"Lawrence, Mississippi","coordinates":[-90.10752,31.55]}, {"dem":1344,"rep":4729,"total":6364,"name":"Pawnee, Oklahoma","coordinates":[-96.69666,36.3137]}, {"dem":2306,"rep":3569,"total":6363,"name":"Koochiching, Minnesota","coordinates":[-93.78289,48.24537]}, {"dem":1020,"rep":5021,"total":6350,"name":"Clay, Illinois","coordinates":[-88.48232,38.74681]}, {"dem":2528,"rep":3701,"total":6336,"name":"Brooks, Georgia","coordinates":[-83.5819,30.82293]}, {"dem":1571,"rep":4587,"total":6334,"name":"Gonzales, Texas","coordinates":[-97.49192,29.46191]}, {"dem":1474,"rep":4716,"total":6328,"name":"Benton, Tennessee","coordinates":[-88.07123,36.07094]}, {"dem":1785,"rep":3714,"total":6324,"name":"Torrance, New Mexico","coordinates":[-105.89055,34.55497]}, {"dem":2106,"rep":3793,"total":6319,"name":"Pope, Minnesota","coordinates":[-95.4467,45.58962]}, {"dem":1501,"rep":4431,"total":6314,"name":"Neosho, Kansas","coordinates":[-95.31568,37.56428]}, {"dem":619,"rep":5567,"total":6301,"name":"Brantley, Georgia","coordinates":[-81.98297,31.19733]}, {"dem":1011,"rep":5021,"total":6288,"name":"Cedar, Missouri","coordinates":[-93.85001,37.73365]}, {"dem":1481,"rep":4455,"total":6283,"name":"Moultrie, Illinois","coordinates":[-88.62572,39.63689]}, {"dem":2314,"rep":3616,"total":6279,"name":"Dakota, Nebraska","coordinates":[-96.56135,42.39164]}, {"dem":1664,"rep":4513,"total":6267,"name":"Crenshaw, Alabama","coordinates":[-86.31922,31.73282]}, {"dem":1359,"rep":4519,"total":6265,"name":"Wetzel, West Virginia","coordinates":[-80.63539,39.59818]}, {"dem":1348,"rep":4722,"total":6260,"name":"Fleming, Kentucky","coordinates":[-83.6992,38.36784]}, {"dem":1679,"rep":4192,"total":6258,"name":"Cherokee, Iowa","coordinates":[-95.63326,42.74273]}, {"dem":1012,"rep":5053,"total":6247,"name":"Union, Tennessee","coordinates":[-83.83608,36.28414]}, {"dem":965,"rep":5051,"total":6242,"name":"Dade, Georgia","coordinates":[-85.5062,34.85242]}, {"dem":3720,"rep":2466,"total":6237,"name":"Jefferson Davis, Mississippi","coordinates":[-89.82708,31.5648]}, {"dem":1978,"rep":3764,"total":6222,"name":"Chippewa, Minnesota","coordinates":[-95.5641,45.02862]}, {"dem":3898,"rep":2204,"total":6214,"name":"Bamberg, South Carolina","coordinates":[-81.05316,33.20302]}, {"dem":1939,"rep":3826,"total":6212,"name":"Arkansas, Arkansas","coordinates":[-91.37654,34.28956]}, {"dem":1331,"rep":4701,"total":6211,"name":"Union, Kentucky","coordinates":[-87.95164,37.65802]}, {"dem":1438,"rep":4629,"total":6203,"name":"McDowell, West Virginia","coordinates":[-81.65818,37.38272]}, {"dem":1732,"rep":4201,"total":6198,"name":"Alcona, Michigan","coordinates":[-82.83407,44.68253]}, {"dem":3255,"rep":2686,"total":6172,"name":"Northampton, Virginia","coordinates":[-75.92401,37.30277]}, {"dem":3510,"rep":2564,"total":6165,"name":"Washington, North Carolina","coordinates":[-76.57229,35.84471]}, {"dem":1814,"rep":4033,"total":6136,"name":"Appanoose, Iowa","coordinates":[-92.87306,40.74429]}, {"dem":786,"rep":5156,"total":6131,"name":"Kingfisher, Oklahoma","coordinates":[-97.93455,35.94943]}, {"dem":2196,"rep":3565,"total":6124,"name":"Swain, North Carolina","coordinates":[-83.46561,35.56884]}, {"dem":4339,"rep":1737,"total":6118,"name":"Wilcox, Alabama","coordinates":[-87.30493,31.99008]}, {"dem":2085,"rep":3744,"total":6097,"name":"Mackinac, Michigan","coordinates":[-85.30376,46.16786]}, {"dem":1290,"rep":4521,"total":6094,"name":"Lawrence, Illinois","coordinates":[-87.73022,38.71895]}, {"dem":1336,"rep":4424,"total":6093,"name":"Bourbon, Kansas","coordinates":[-94.85092,37.85609]}, {"dem":1142,"rep":4649,"total":6089,"name":"Johnson, Illinois","coordinates":[-88.88213,37.4607]}, {"dem":2925,"rep":2638,"total":6085,"name":"Radford, Virginia","coordinates":[-80.55914,37.12011]}, {"dem":1241,"rep":4655,"total":6081,"name":"Calhoun, Florida","coordinates":[-85.19791,30.3888]}, {"dem":2582,"rep":3376,"total":6077,"name":"Yalobusha, Mississippi","coordinates":[-89.7038,34.03066]}, {"dem":1753,"rep":4176,"total":6057,"name":"Cook, Georgia","coordinates":[-83.42944,31.15251]}, {"dem":1222,"rep":4527,"total":6054,"name":"Barbour, West Virginia","coordinates":[-79.99694,39.13972]}, {"dem":1544,"rep":4360,"total":6045,"name":"Jasper, Georgia","coordinates":[-83.68915,33.31698]}, {"dem":1045,"rep":4816,"total":6042,"name":"Lawrence, Kentucky","coordinates":[-82.73829,38.07445]}, {"dem":1947,"rep":3964,"total":6027,"name":"Pemiscot, Missouri","coordinates":[-89.78594,36.20991]}, {"dem":1896,"rep":3800,"total":6026,"name":"Wright, Iowa","coordinates":[-93.73473,42.733]}, {"dem":2108,"rep":3670,"total":6017,"name":"Middlesex, Virginia","coordinates":[-76.52808,37.60697]}, {"dem":1744,"rep":4125,"total":6015,"name":"Franklin, Florida","coordinates":[-84.79917,29.81017]}, {"dem":1221,"rep":4549,"total":6013,"name":"Noble, Ohio","coordinates":[-81.45249,39.76723]}, {"dem":1367,"rep":4437,"total":6010,"name":"Clay, North Carolina","coordinates":[-83.75226,35.05299]}, {"dem":1164,"rep":4604,"total":6007,"name":"Pendleton, Kentucky","coordinates":[-84.35194,38.69628]}, {"dem":1828,"rep":3748,"total":5991,"name":"Carbon, Montana","coordinates":[-109.02855,45.22446]}, {"dem":1154,"rep":4737,"total":5985,"name":"Trinity, Texas","coordinates":[-95.15168,31.09667]}, {"dem":1789,"rep":3785,"total":5984,"name":"Marshall, Illinois","coordinates":[-89.34237,41.03111]}, {"dem":1297,"rep":4398,"total":5977,"name":"Pike, Indiana","coordinates":[-87.23254,38.39796]}, {"dem":1260,"rep":4507,"total":5975,"name":"Caldwell, Kentucky","coordinates":[-87.8705,37.14864]}, {"dem":3353,"rep":2497,"total":5964,"name":"St. Helena, Louisiana","coordinates":[-90.7083,30.82253]}, {"dem":936,"rep":4819,"total":5960,"name":"Jones, Texas","coordinates":[-99.87442,32.7437]}, {"dem":1218,"rep":4286,"total":5953,"name":"Sanders, Montana","coordinates":[-115.1803,47.75649]}, {"dem":1575,"rep":4003,"total":5951,"name":"La Paz, Arizona","coordinates":[-114.0388,33.72761]}, {"dem":1454,"rep":3884,"total":5950,"name":"Roosevelt, New Mexico","coordinates":[-103.483,34.0212]}, {"dem":795,"rep":4959,"total":5939,"name":"Barton, Missouri","coordinates":[-94.34408,37.50079]}, {"dem":2101,"rep":3739,"total":5936,"name":"Ben Hill, Georgia","coordinates":[-83.14719,31.74077]}, {"dem":2004,"rep":3675,"total":5910,"name":"Iron, Michigan","coordinates":[-88.54052,46.17025]}, {"dem":3533,"rep":2149,"total":5907,"name":"Martinsville, Virginia","coordinates":[-79.86364,36.68352]}, {"dem":2303,"rep":3487,"total":5903,"name":"McIntosh, Georgia","coordinates":[-81.37228,31.4885]}, {"dem":1587,"rep":3977,"total":5871,"name":"Hancock, Iowa","coordinates":[-93.74369,43.07541]}, {"dem":3337,"rep":2462,"total":5870,"name":"Tallahatchie, Mississippi","coordinates":[-90.17224,33.95452]}, {"dem":2729,"rep":2575,"total":5866,"name":"Clear Creek, Colorado","coordinates":[-105.69256,39.66973]}, {"dem":717,"rep":5036,"total":5857,"name":"Wayne, Tennessee","coordinates":[-87.81984,35.24284]}, {"dem":1202,"rep":4269,"total":5840,"name":"Fergus, Montana","coordinates":[-109.23213,47.22522]}, {"dem":1922,"rep":3525,"total":5832,"name":"Union, Iowa","coordinates":[-94.24509,41.02855]}, {"dem":1512,"rep":3939,"total":5818,"name":"Jackson, Kansas","coordinates":[-95.79448,39.41114]}, {"dem":2155,"rep":3479,"total":5808,"name":"Charlotte, Virginia","coordinates":[-78.65856,37.00904]}, {"dem":1240,"rep":4397,"total":5805,"name":"Webster, Kentucky","coordinates":[-87.68479,37.51945]}, {"dem":1111,"rep":4443,"total":5805,"name":"Monroe, West Virginia","coordinates":[-80.55032,37.55406]}, {"dem":2248,"rep":3390,"total":5799,"name":"West Feliciana, Louisiana","coordinates":[-91.421,30.8727]}, {"dem":924,"rep":4418,"total":5796,"name":"Goshen, Wyoming","coordinates":[-104.35354,42.08945]}, {"dem":1404,"rep":4077,"total":5795,"name":"Newton, Indiana","coordinates":[-87.40217,40.96239]}, {"dem":1931,"rep":3447,"total":5787,"name":"Winnebago, Iowa","coordinates":[-93.74348,43.37812]}, {"dem":1252,"rep":4283,"total":5785,"name":"Craig, Oklahoma","coordinates":[-95.20155,36.76388]}, {"dem":858,"rep":4621,"total":5780,"name":"Texas, Oklahoma","coordinates":[-101.48385,36.74631]}, {"dem":664,"rep":5012,"total":5776,"name":"McCreary, Kentucky","coordinates":[-84.49105,36.73113]}, {"dem":1245,"rep":4357,"total":5763,"name":"Knott, Kentucky","coordinates":[-82.95254,37.35436]}, {"dem":1732,"rep":3628,"total":5750,"name":"Guthrie, Iowa","coordinates":[-94.50127,41.68357]}, {"dem":1537,"rep":3991,"total":5738,"name":"Breathitt, Kentucky","coordinates":[-83.31715,37.5178]}, {"dem":1678,"rep":3679,"total":5721,"name":"Cottonwood, Minnesota","coordinates":[-95.18315,44.01063]}, {"dem":2300,"rep":3305,"total":5715,"name":"Screven, Georgia","coordinates":[-81.61758,32.74475]}, {"dem":651,"rep":4090,"total":5715,"name":"Fremont, Idaho","coordinates":[-111.48442,44.21809]}, {"dem":1244,"rep":4108,"total":5713,"name":"Lincoln, Washington","coordinates":[-118.41769,47.58274]}, {"dem":1014,"rep":4568,"total":5694,"name":"Union, Florida","coordinates":[-82.36691,30.05427]}, {"dem":1053,"rep":4441,"total":5694,"name":"Sequatchie, Tennessee","coordinates":[-85.41008,35.37233]}, {"dem":2214,"rep":2812,"total":5686,"name":"Trinity, California","coordinates":[-123.11447,40.6478]}, {"dem":1263,"rep":4064,"total":5685,"name":"Lawrence, Arkansas","coordinates":[-91.10115,36.04109]}, {"dem":1244,"rep":4212,"total":5685,"name":"Blanco, Texas","coordinates":[-98.39921,30.26645]}, {"dem":705,"rep":4827,"total":5676,"name":"Bollinger, Missouri","coordinates":[-90.02464,37.31842]}, {"dem":948,"rep":4658,"total":5655,"name":"Wayne, Missouri","coordinates":[-90.45393,37.11107]}, {"dem":641,"rep":4695,"total":5652,"name":"Custer, Nebraska","coordinates":[-99.72686,41.39389]}, {"dem":1155,"rep":4274,"total":5643,"name":"Hardy, West Virginia","coordinates":[-78.84172,39.01136]}, {"dem":2232,"rep":2928,"total":5639,"name":"Skamania, Washington","coordinates":[-121.95323,46.02478]}, {"dem":1420,"rep":4013,"total":5636,"name":"Washington, Kentucky","coordinates":[-85.17541,37.7542]}, {"dem":1204,"rep":4003,"total":5624,"name":"Marion, Kansas","coordinates":[-97.10277,38.35964]}, {"dem":1203,"rep":4113,"total":5618,"name":"Stone, Arkansas","coordinates":[-92.14048,35.857]}, {"dem":1240,"rep":4088,"total":5587,"name":"Linn, Missouri","coordinates":[-93.10801,39.86444]}, {"dem":2227,"rep":3204,"total":5586,"name":"Lunenburg, Virginia","coordinates":[-78.24052,36.94555]}, {"dem":1205,"rep":4145,"total":5585,"name":"Greene, Illinois","coordinates":[-90.38768,39.35543]}, {"dem":569,"rep":4865,"total":5579,"name":"Callahan, Texas","coordinates":[-99.37224,32.29314]}, {"dem":947,"rep":4428,"total":5576,"name":"Butler, Kentucky","coordinates":[-86.68247,37.20701]}, {"dem":4347,"rep":1200,"total":5574,"name":"Noxubee, Mississippi","coordinates":[-88.566,33.1065]}, {"dem":1031,"rep":4206,"total":5567,"name":"Cumberland, Illinois","coordinates":[-88.24061,39.27312]}, {"dem":1108,"rep":4236,"total":5545,"name":"Estill, Kentucky","coordinates":[-83.96398,37.69244]}, {"dem":2001,"rep":3085,"total":5534,"name":"Rio Grande, Colorado","coordinates":[-106.45312,37.48585]}, {"dem":1156,"rep":4288,"total":5534,"name":"Newton, Texas","coordinates":[-93.73925,30.78671]}, {"dem":1680,"rep":3799,"total":5528,"name":"Carroll, Mississippi","coordinates":[-89.91888,33.44079]}, {"dem":1087,"rep":4175,"total":5528,"name":"Murray, Oklahoma","coordinates":[-97.07155,34.48576]}, {"dem":830,"rep":4522,"total":5524,"name":"Ripley, Missouri","coordinates":[-90.87483,36.65017]}, {"dem":1351,"rep":3883,"total":5502,"name":"Vinton, Ohio","coordinates":[-82.48596,39.25204]}, {"dem":482,"rep":4889,"total":5501,"name":"Jackson, Kentucky","coordinates":[-84.02057,37.40345]}, {"dem":385,"rep":3901,"total":5499,"name":"Franklin, Idaho","coordinates":[-111.82296,42.1736]}, {"dem":1096,"rep":4206,"total":5492,"name":"Marshall, Oklahoma","coordinates":[-96.77053,34.027]}, {"dem":1492,"rep":3609,"total":5484,"name":"Jackson, Minnesota","coordinates":[-95.14973,43.67111]}, {"dem":1151,"rep":4047,"total":5464,"name":"Wabash, Illinois","coordinates":[-87.83916,38.44582]}, {"dem":1904,"rep":3443,"total":5460,"name":"Hamilton, Florida","coordinates":[-82.95107,30.49118]}, {"dem":1327,"rep":3854,"total":5459,"name":"Pulaski, Indiana","coordinates":[-86.69253,41.04527]}, {"dem":1433,"rep":3651,"total":5454,"name":"Allen, Kansas","coordinates":[-95.30094,37.88422]}, {"dem":1113,"rep":4042,"total":5448,"name":"Izard, Arkansas","coordinates":[-91.91362,36.09487]}, {"dem":2042,"rep":2645,"total":5447,"name":"San Juan, Utah","coordinates":[-109.79157,37.60263]}, {"dem":1220,"rep":4135,"total":5432,"name":"Perry, Mississippi","coordinates":[-88.98875,31.1693]}, {"dem":1119,"rep":4127,"total":5429,"name":"Montgomery, Missouri","coordinates":[-91.46542,38.93518]}, {"dem":1067,"rep":4206,"total":5426,"name":"Choctaw, Oklahoma","coordinates":[-95.5542,34.02764]}, {"dem":1888,"rep":3190,"total":5417,"name":"Mitchell, Iowa","coordinates":[-92.78446,43.34856]}, {"dem":2542,"rep":2657,"total":5408,"name":"Essex, Virginia","coordinates":[-76.94187,37.93948]}, {"dem":2116,"rep":2799,"total":5398,"name":"Stevens, Minnesota","coordinates":[-95.99231,45.59346]}, {"dem":1303,"rep":3982,"total":5397,"name":"Crockett, Tennessee","coordinates":[-89.13249,35.81879]}, {"dem":2385,"rep":2874,"total":5392,"name":"Gates, North Carolina","coordinates":[-76.70235,36.44213]}, {"dem":974,"rep":4335,"total":5369,"name":"Greene, Mississippi","coordinates":[-88.63481,31.21284]}, {"dem":1913,"rep":2906,"total":5349,"name":"Valley, Idaho","coordinates":[-115.61806,44.85595]}, {"dem":1597,"rep":3160,"total":5344,"name":"Barnes, North Dakota","coordinates":[-98.07019,46.94255]}, {"dem":832,"rep":4372,"total":5333,"name":"Green, Kentucky","coordinates":[-85.57848,37.27538]}, {"dem":2129,"rep":2585,"total":5332,"name":"Colfax, New Mexico","coordinates":[-104.64011,36.61296]}, {"dem":1939,"rep":3159,"total":5328,"name":"Lake, Michigan","coordinates":[-85.81139,43.99518]}, {"dem":1005,"rep":4102,"total":5321,"name":"Madison, Missouri","coordinates":[-90.34341,37.47448]}, {"dem":604,"rep":4067,"total":5317,"name":"Big Horn, Wyoming","coordinates":[-107.99484,44.52511]}, {"dem":1306,"rep":3814,"total":5315,"name":"Alleghany, North Carolina","coordinates":[-81.13229,36.48935]}, {"dem":1081,"rep":3860,"total":5315,"name":"McLean, North Dakota","coordinates":[-101.35308,47.53045]}, {"dem":1127,"rep":4007,"total":5314,"name":"Cannon, Tennessee","coordinates":[-86.0624,35.80839]}, {"dem":1563,"rep":3517,"total":5311,"name":"Mathews, Virginia","coordinates":[-76.2688,37.42534]}, {"dem":1505,"rep":3217,"total":5305,"name":"Ramsey, North Dakota","coordinates":[-98.73903,48.26616]}, {"dem":904,"rep":4266,"total":5302,"name":"Jackson, Texas","coordinates":[-96.58908,28.9598]}, {"dem":1222,"rep":3864,"total":5299,"name":"Stewart, Tennessee","coordinates":[-87.81188,36.45846]}, {"dem":785,"rep":4363,"total":5298,"name":"Lewis, Kentucky","coordinates":[-83.37014,38.53504]}, {"dem":733,"rep":4410,"total":5289,"name":"Scurry, Texas","coordinates":[-100.91334,32.74435]}, {"dem":1098,"rep":3977,"total":5284,"name":"Moore, Texas","coordinates":[-101.8905,35.83567]}, {"dem":3824,"rep":1407,"total":5278,"name":"Perry, Alabama","coordinates":[-87.29382,32.639]}, {"dem":2773,"rep":2111,"total":5276,"name":"Mono, California","coordinates":[-118.87516,37.91583]}, {"dem":1524,"rep":3382,"total":5276,"name":"Yellow Medicine, Minnesota","coordinates":[-95.86275,44.71573]}, {"dem":1138,"rep":3969,"total":5266,"name":"Ralls, Missouri","coordinates":[-91.52478,39.55345]}, {"dem":1782,"rep":3381,"total":5252,"name":"Coosa, Alabama","coordinates":[-86.24348,32.93144]}, {"dem":1684,"rep":3441,"total":5248,"name":"Falls, Texas","coordinates":[-96.93412,31.25192]}, {"dem":1222,"rep":3781,"total":5247,"name":"Roane, West Virginia","coordinates":[-81.35449,38.74294]}, {"dem":979,"rep":4135,"total":5244,"name":"Edmonson, Kentucky","coordinates":[-86.21801,37.22751]}, {"dem":431,"rep":3860,"total":5242,"name":"Millard, Utah","coordinates":[-113.13309,38.95674]}, {"dem":789,"rep":4333,"total":5237,"name":"Comanche, Texas","coordinates":[-98.54961,31.95164]}, {"dem":3204,"rep":1733,"total":5232,"name":"Manassas Park, Virginia","coordinates":[-77.44876,38.76894]}, {"dem":1397,"rep":3605,"total":5227,"name":"Little River, Arkansas","coordinates":[-94.22977,33.69949]}, {"dem":2479,"rep":2652,"total":5216,"name":"McCormick, South Carolina","coordinates":[-82.31619,33.89759]}, {"dem":1270,"rep":3703,"total":5212,"name":"Sac, Iowa","coordinates":[-95.10522,42.38752]}, {"dem":1199,"rep":3781,"total":5200,"name":"Clay, Arkansas","coordinates":[-90.4187,36.3673]}, {"dem":577,"rep":3188,"total":5192,"name":"Morgan, Utah","coordinates":[-111.57788,41.09102]}, {"dem":930,"rep":3743,"total":5191,"name":"Gooding, Idaho","coordinates":[-114.82142,42.97318]}, {"dem":1176,"rep":3657,"total":5185,"name":"Custer, Montana","coordinates":[-105.55035,46.26141]}, {"dem":1612,"rep":3010,"total":5181,"name":"Sierra, New Mexico","coordinates":[-107.18816,33.11946]}, {"dem":1421,"rep":3635,"total":5176,"name":"Crawford, Georgia","coordinates":[-83.97918,32.70942]}, {"dem":645,"rep":4258,"total":5170,"name":"Red Willow, Nebraska","coordinates":[-100.46857,40.16941]}, {"dem":1458,"rep":3600,"total":5169,"name":"Mississippi, Missouri","coordinates":[-89.29592,36.82626]}, {"dem":933,"rep":3789,"total":5163,"name":"Boundary, Idaho","coordinates":[-116.52466,48.77313]}, {"dem":1149,"rep":3926,"total":5161,"name":"Red River, Texas","coordinates":[-95.04842,33.61962]}, {"dem":1398,"rep":3468,"total":5159,"name":"Calhoun, Iowa","coordinates":[-94.64368,42.38616]}, {"dem":1583,"rep":3267,"total":5156,"name":"Jackson, Arkansas","coordinates":[-91.2232,35.59646]}, {"dem":924,"rep":3975,"total":5136,"name":"Jasper, Illinois","coordinates":[-88.15076,39.00487]}, {"dem":1733,"rep":3004,"total":5136,"name":"Saline, Nebraska","coordinates":[-97.13175,40.5168]}, {"dem":2065,"rep":2974,"total":5135,"name":"Jones, North Carolina","coordinates":[-77.35619,35.03226]}, {"dem":1621,"rep":3216,"total":5124,"name":"Cass, Illinois","coordinates":[-90.2457,39.9692]}, {"dem":725,"rep":4124,"total":5122,"name":"Nemaha, Kansas","coordinates":[-96.00538,39.79104]}, {"dem":1384,"rep":3297,"total":5120,"name":"Shoshone, Idaho","coordinates":[-115.88509,47.34769]}, {"dem":531,"rep":4354,"total":5118,"name":"Holt, Nebraska","coordinates":[-98.78476,42.45928]}, {"dem":1172,"rep":3824,"total":5116,"name":"Magoffin, Kentucky","coordinates":[-83.06972,37.69898]}, {"dem":901,"rep":4104,"total":5096,"name":"Jeff Davis, Georgia","coordinates":[-82.63682,31.81161]}, {"dem":3422,"rep":1547,"total":5095,"name":"Willacy, Texas","coordinates":[-97.59473,26.48186]}, {"dem":1321,"rep":3537,"total":5090,"name":"Braxton, West Virginia","coordinates":[-80.73165,38.69933]}, {"dem":1252,"rep":3568,"total":5087,"name":"Humboldt, Iowa","coordinates":[-94.20277,42.78222]}, {"dem":3121,"rep":1620,"total":5075,"name":"Glacier, Montana","coordinates":[-112.9905,48.70567]}, {"dem":1019,"rep":3976,"total":5069,"name":"Webster, Mississippi","coordinates":[-89.28396,33.61206]}, {"dem":2608,"rep":2109,"total":5069,"name":"Clay, South Dakota","coordinates":[-96.98046,42.91614]}, {"dem":1314,"rep":3436,"total":5044,"name":"Montgomery, Iowa","coordinates":[-95.15778,41.02173]}, {"dem":2879,"rep":2055,"total":5044,"name":"Sussex, Virginia","coordinates":[-77.25973,36.92664]}, {"dem":1628,"rep":3159,"total":5038,"name":"Seward, Kansas","coordinates":[-100.85525,37.18095]}, {"dem":795,"rep":4084,"total":5018,"name":"Atoka, Oklahoma","coordinates":[-96.03655,34.39246]}, {"dem":536,"rep":4377,"total":5018,"name":"Clay, Texas","coordinates":[-98.21291,33.7859]}, {"dem":1186,"rep":3531,"total":5016,"name":"Prowers, Colorado","coordinates":[-102.39216,37.95818]}, {"dem":1287,"rep":3498,"total":5009,"name":"Montmorency, Michigan","coordinates":[-84.1301,45.02413]}, {"dem":1648,"rep":3069,"total":5008,"name":"Louisa, Iowa","coordinates":[-91.25699,41.21821]}, {"dem":1274,"rep":3546,"total":5006,"name":"Camden, North Carolina","coordinates":[-76.16248,36.34234]}, {"dem":878,"rep":3783,"total":5004,"name":"Hamilton, Nebraska","coordinates":[-98.02232,40.87281]}, {"dem":1062,"rep":3745,"total":5001,"name":"Owen, Kentucky","coordinates":[-84.84159,38.49939]}, {"dem":1814,"rep":2768,"total":4998,"name":"Watonwan, Minnesota","coordinates":[-94.61379,43.9781]}, {"dem":2115,"rep":2818,"total":4996,"name":"Montgomery, Mississippi","coordinates":[-89.63962,33.50071]}, {"dem":1686,"rep":2963,"total":4994,"name":"Swift, Minnesota","coordinates":[-95.69012,45.27581]}, {"dem":601,"rep":4278,"total":4991,"name":"Monroe, Kentucky","coordinates":[-85.7135,36.71407]}, {"dem":1342,"rep":3390,"total":4985,"name":"Keokuk, Iowa","coordinates":[-92.16772,41.33118]}, {"dem":2159,"rep":2167,"total":4976,"name":"Teton, Idaho","coordinates":[-111.21176,43.76099]}, {"dem":1101,"rep":3719,"total":4974,"name":"Bleckley, Georgia","coordinates":[-83.33171,32.4354]}, {"dem":1425,"rep":3446,"total":4973,"name":"Morris, Texas","coordinates":[-94.73126,33.11646]}, {"dem":1493,"rep":3163,"total":4968,"name":"Franklin, Iowa","coordinates":[-93.27141,42.73654]}, {"dem":1272,"rep":3513,"total":4957,"name":"Powell, Kentucky","coordinates":[-83.83135,37.8099]}, {"dem":512,"rep":4346,"total":4956,"name":"Grant, West Virginia","coordinates":[-79.19506,39.10598]}, {"dem":836,"rep":3927,"total":4943,"name":"Andrews, Texas","coordinates":[-102.6402,32.31225]}, {"dem":965,"rep":3617,"total":4924,"name":"Box Butte, Nebraska","coordinates":[-103.08177,42.21038]}, {"dem":2036,"rep":2697,"total":4906,"name":"Cumberland, Virginia","coordinates":[-78.25283,37.52018]}, {"dem":4013,"rep":838,"total":4880,"name":"Greene, Alabama","coordinates":[-87.9642,32.84449]}, {"dem":901,"rep":3715,"total":4878,"name":"Noble, Oklahoma","coordinates":[-97.23633,36.3849]}, {"dem":908,"rep":3661,"total":4873,"name":"Stillwater, Montana","coordinates":[-109.38157,45.65854]}, {"dem":671,"rep":3908,"total":4871,"name":"Richland, Montana","coordinates":[-104.5634,47.78563]}, {"dem":1283,"rep":3277,"total":4868,"name":"Howard, Missouri","coordinates":[-92.69592,39.14336]}, {"dem":1190,"rep":3455,"total":4862,"name":"Summers, West Virginia","coordinates":[-80.85632,37.65599]}, {"dem":1029,"rep":3552,"total":4857,"name":"Nolan, Texas","coordinates":[-100.4181,32.31233]}, {"dem":1322,"rep":3479,"total":4856,"name":"Catahoula, Louisiana","coordinates":[-91.8467,31.66651]}, {"dem":1143,"rep":3353,"total":4849,"name":"Beaverhead, Montana","coordinates":[-112.89286,45.13386]}, {"dem":1243,"rep":3350,"total":4839,"name":"Blackford, Indiana","coordinates":[-85.32372,40.47267]}, {"dem":1373,"rep":3091,"total":4839,"name":"Rock, Minnesota","coordinates":[-96.26323,43.66958]}, {"dem":1691,"rep":2820,"total":4821,"name":"Greene, Iowa","coordinates":[-94.3887,42.04249]}, {"dem":1225,"rep":3208,"total":4817,"name":"Marshall, Minnesota","coordinates":[-96.35776,48.36272]}, {"dem":881,"rep":3697,"total":4809,"name":"Martin, Indiana","coordinates":[-86.80184,38.70532]}, {"dem":1127,"rep":3338,"total":4808,"name":"Pipestone, Minnesota","coordinates":[-96.25701,44.01536]}, {"dem":726,"rep":3850,"total":4791,"name":"Yuma, Colorado","coordinates":[-102.42164,40.00077]}, {"dem":2168,"rep":2552,"total":4785,"name":"Early, Georgia","coordinates":[-84.90672,31.32419]}, {"dem":1042,"rep":3612,"total":4779,"name":"Todd, Kentucky","coordinates":[-87.18364,36.84033]}, {"dem":1180,"rep":3297,"total":4778,"name":"Madison, Montana","coordinates":[-111.91379,45.32528]}, {"dem":1006,"rep":3628,"total":4775,"name":"Morgan, Kentucky","coordinates":[-83.25894,37.92294]}, {"dem":1067,"rep":3471,"total":4772,"name":"Fulton, Arkansas","coordinates":[-91.81966,36.38361]}, {"dem":999,"rep":3636,"total":4763,"name":"Grundy, Tennessee","coordinates":[-85.71037,35.39338]}, {"dem":715,"rep":3970,"total":4759,"name":"West Carroll, Louisiana","coordinates":[-91.45199,32.79247]}, {"dem":1357,"rep":3124,"total":4753,"name":"Emmet, Iowa","coordinates":[-94.66937,43.37798]}, {"dem":882,"rep":3701,"total":4738,"name":"Haskell, Oklahoma","coordinates":[-95.10957,35.23229]}, {"dem":2744,"rep":1927,"total":4732,"name":"Madison, Louisiana","coordinates":[-91.23193,32.34687]}, {"dem":1016,"rep":3542,"total":4724,"name":"Hickory, Missouri","coordinates":[-93.32298,37.9369]}, {"dem":1121,"rep":3293,"total":4721,"name":"Custer, South Dakota","coordinates":[-103.46225,43.68494]}, {"dem":711,"rep":3665,"total":4711,"name":"Cheyenne, Nebraska","coordinates":[-103.01192,41.21423]}, {"dem":3530,"rep":1140,"total":4710,"name":"Bullock, Alabama","coordinates":[-85.71726,32.10175]}, {"dem":1398,"rep":3081,"total":4703,"name":"Palo Alto, Iowa","coordinates":[-94.66905,43.07533]}, {"dem":628,"rep":3968,"total":4701,"name":"Rains, Texas","coordinates":[-95.79544,32.87057]}, {"dem":572,"rep":3849,"total":4695,"name":"Phelps, Nebraska","coordinates":[-99.40655,40.51636]}, {"dem":788,"rep":3822,"total":4692,"name":"Caldwell, Louisiana","coordinates":[-92.11423,32.10121]}, {"dem":621,"rep":3759,"total":4682,"name":"Mercer, North Dakota","coordinates":[-101.83332,47.30714]}, {"dem":1351,"rep":3157,"total":4674,"name":"Howard, Arkansas","coordinates":[-93.99093,34.08306]}, {"dem":1072,"rep":3307,"total":4673,"name":"Marshall, Kansas","coordinates":[-96.52124,39.7827]}, {"dem":698,"rep":3670,"total":4672,"name":"McKenzie, North Dakota","coordinates":[-103.40321,47.74247]}, {"dem":1295,"rep":2974,"total":4668,"name":"Murray, Minnesota","coordinates":[-95.76158,44.01559]}, {"dem":865,"rep":3671,"total":4668,"name":"Oregon, Missouri","coordinates":[-91.40182,36.68531]}, {"dem":897,"rep":3622,"total":4664,"name":"Bledsoe, Tennessee","coordinates":[-85.20591,35.59356]}, {"dem":614,"rep":3998,"total":4651,"name":"Sabine, Texas","coordinates":[-93.85191,31.34329]}, {"dem":887,"rep":3570,"total":4645,"name":"Livingston, Kentucky","coordinates":[-88.36342,37.20951]}, {"dem":1299,"rep":3083,"total":4644,"name":"Adams, Washington","coordinates":[-118.51286,47.01123]}, {"dem":2827,"rep":1778,"total":4639,"name":"Kemper, Mississippi","coordinates":[-88.62563,32.75013]}, {"dem":1167,"rep":2995,"total":4636,"name":"Walsh, North Dakota","coordinates":[-97.72223,48.37697]}, {"dem":588,"rep":3854,"total":4631,"name":"Washita, Oklahoma","coordinates":[-98.99143,35.28949]}, {"dem":936,"rep":3501,"total":4630,"name":"St. Clair, Missouri","coordinates":[-93.77656,38.04223]}, {"dem":890,"rep":3585,"total":4622,"name":"Lewis, Tennessee","coordinates":[-87.49698,35.52324]}, {"dem":976,"rep":3491,"total":4620,"name":"Metcalfe, Kentucky","coordinates":[-85.63345,36.99242]}, {"dem":597,"rep":3907,"total":4620,"name":"Gaines, Texas","coordinates":[-102.63156,32.74394]}, {"dem":824,"rep":3540,"total":4594,"name":"DeKalb, Missouri","coordinates":[-94.40719,39.89466]}, {"dem":1323,"rep":3015,"total":4593,"name":"Crawford, Indiana","coordinates":[-86.44087,38.28943]}, {"dem":894,"rep":3588,"total":4592,"name":"Decatur, Tennessee","coordinates":[-88.11029,35.60313]}, {"dem":1361,"rep":3082,"total":4587,"name":"Bath, Kentucky","coordinates":[-83.73764,38.15224]}, {"dem":1247,"rep":3120,"total":4572,"name":"Monona, Iowa","coordinates":[-95.95656,42.04943]}, {"dem":988,"rep":3381,"total":4566,"name":"McLean, Kentucky","coordinates":[-87.26559,37.5267]}, {"dem":1075,"rep":3282,"total":4562,"name":"Sevier, Arkansas","coordinates":[-94.24327,33.99487]}, {"dem":1677,"rep":2611,"total":4559,"name":"Howard, Iowa","coordinates":[-92.3219,43.36531]}, {"dem":1260,"rep":3201,"total":4542,"name":"Camp, Texas","coordinates":[-94.97908,32.97458]}, {"dem":1584,"rep":2788,"total":4540,"name":"Forest, Wisconsin","coordinates":[-88.77332,45.66688]}, {"dem":1960,"rep":1975,"total":4533,"name":"Grand, Utah","coordinates":[-109.57345,38.97432]}, {"dem":719,"rep":3437,"total":4529,"name":"Platte, Wyoming","coordinates":[-104.95396,42.13159]}, {"dem":961,"rep":3388,"total":4526,"name":"Hughes, Oklahoma","coordinates":[-96.25118,35.05293]}, {"dem":1663,"rep":2585,"total":4518,"name":"Alger, Michigan","coordinates":[-86.5641,47.08007]}, {"dem":724,"rep":3639,"total":4505,"name":"Ozark, Missouri","coordinates":[-92.45854,36.64959]}, {"dem":794,"rep":3561,"total":4500,"name":"Maries, Missouri","coordinates":[-91.9236,38.16261]}, {"dem":400,"rep":4015,"total":4492,"name":"Leslie, Kentucky","coordinates":[-83.38861,37.08784]}, {"dem":1848,"rep":2572,"total":4486,"name":"Wilkes, Georgia","coordinates":[-82.74792,33.77903]}, {"dem":748,"rep":3581,"total":4483,"name":"Pushmataha, Oklahoma","coordinates":[-95.40808,34.37789]}, {"dem":1747,"rep":2539,"total":4483,"name":"Rappahannock, Virginia","coordinates":[-78.16882,38.68452]}, {"dem":1129,"rep":3236,"total":4466,"name":"Jackson, Tennessee","coordinates":[-85.67412,36.35424]}, {"dem":547,"rep":3809,"total":4462,"name":"Clinton, Kentucky","coordinates":[-85.13609,36.72725]}, {"dem":934,"rep":3344,"total":4456,"name":"Lewis, Missouri","coordinates":[-91.7288,40.08455]}, {"dem":776,"rep":3283,"total":4455,"name":"Washington, Idaho","coordinates":[-116.79779,44.44822]}, {"dem":1465,"rep":2713,"total":4454,"name":"Clarke, Iowa","coordinates":[-93.78409,41.02919]}, {"dem":736,"rep":3484,"total":4427,"name":"Linn, Kansas","coordinates":[-94.84493,38.21654]}, {"dem":1938,"rep":2391,"total":4422,"name":"Red River, Louisiana","coordinates":[-93.34905,32.10121]}, {"dem":571,"rep":3532,"total":4420,"name":"Cedar, Nebraska","coordinates":[-97.25686,42.60456]}, {"dem":638,"rep":3477,"total":4417,"name":"Johnson, Wyoming","coordinates":[-106.58854,44.04404]}, {"dem":2444,"rep":1856,"total":4400,"name":"Frio, Texas","coordinates":[-99.10878,28.86933]}, {"dem":644,"rep":3409,"total":4390,"name":"Sublette, Wyoming","coordinates":[-109.91617,42.76792]}, {"dem":665,"rep":3585,"total":4380,"name":"Franklin, Texas","coordinates":[-95.21906,33.17584]}, {"dem":787,"rep":3320,"total":4374,"name":"Dawson, Montana","coordinates":[-104.89827,47.26613]}, {"dem":1116,"rep":2848,"total":4366,"name":"Wallowa, Oregon","coordinates":[-117.18557,45.59375]}, {"dem":2558,"rep":1737,"total":4363,"name":"Greensville, Virginia","coordinates":[-77.56027,36.68033]}, {"dem":745,"rep":3480,"total":4361,"name":"Carroll, Missouri","coordinates":[-93.50022,39.42737]}, {"dem":1239,"rep":2877,"total":4354,"name":"Lucas, Iowa","coordinates":[-93.33146,41.03334]}, {"dem":1271,"rep":2996,"total":4353,"name":"Glades, Florida","coordinates":[-81.19081,26.95481]}, {"dem":696,"rep":3357,"total":4351,"name":"Butte, South Dakota","coordinates":[-103.50143,44.89622]}, {"dem":739,"rep":3210,"total":4340,"name":"Grant, Oregon","coordinates":[-119.01405,44.49632]}, {"dem":2975,"rep":1033,"total":4329,"name":"San Miguel, Colorado","coordinates":[-108.42726,38.00931]}, {"dem":856,"rep":3342,"total":4320,"name":"Meigs, Tennessee","coordinates":[-84.8161,35.5122]}, {"dem":838,"rep":3232,"total":4312,"name":"Caldwell, Missouri","coordinates":[-93.97917,39.65899]}, {"dem":780,"rep":3462,"total":4310,"name":"Grundy, Missouri","coordinates":[-93.56505,40.11254]}, {"dem":1049,"rep":3008,"total":4306,"name":"Perry, Arkansas","coordinates":[-92.92687,34.94636]}, {"dem":742,"rep":3464,"total":4302,"name":"Live Oak, Texas","coordinates":[-98.12696,28.35153]}, {"dem":1244,"rep":2788,"total":4295,"name":"Hancock, Kentucky","coordinates":[-86.79276,37.84332]}, {"dem":1502,"rep":2721,"total":4290,"name":"Franklin, Mississippi","coordinates":[-90.89545,31.47777]}, {"dem":881,"rep":3351,"total":4289,"name":"Madison, Texas","coordinates":[-95.93037,30.96687]}, {"dem":380,"rep":3425,"total":4289,"name":"Emery, Utah","coordinates":[-110.72109,39.00902]}, {"dem":2705,"rep":1540,"total":4287,"name":"Macon, Georgia","coordinates":[-84.05123,32.36268]}, {"dem":1894,"rep":2333,"total":4287,"name":"Wilkinson, Georgia","coordinates":[-83.17551,32.80426]}, {"dem":394,"rep":3786,"total":4283,"name":"Archer, Texas","coordinates":[-98.68726,33.6163]}, {"dem":3708,"rep":540,"total":4272,"name":"Claiborne, Mississippi","coordinates":[-90.91542,31.9728]}, {"dem":933,"rep":3173,"total":4269,"name":"Iron, Missouri","coordinates":[-90.98468,37.59436]}, {"dem":2228,"rep":1919,"total":4257,"name":"Desha, Arkansas","coordinates":[-91.2441,33.82875]}, {"dem":1530,"rep":2453,"total":4257,"name":"Worth, Iowa","coordinates":[-93.24853,43.37349]}, {"dem":3071,"rep":1151,"total":4253,"name":"Humphreys, Mississippi","coordinates":[-90.52342,33.13099]}, {"dem":1873,"rep":2077,"total":4252,"name":"Brewster, Texas","coordinates":[-103.25245,29.80899]}, {"dem":1100,"rep":2925,"total":4245,"name":"Clearwater, Minnesota","coordinates":[-95.37111,47.57587]}, {"dem":1165,"rep":2983,"total":4238,"name":"Marion, Texas","coordinates":[-94.35685,32.79818]}, {"dem":2094,"rep":1853,"total":4237,"name":"Big Horn, Montana","coordinates":[-107.51816,45.40786]}, {"dem":742,"rep":3321,"total":4237,"name":"Nowata, Oklahoma","coordinates":[-95.61331,36.78961]}, {"dem":2272,"rep":1819,"total":4228,"name":"Surry, Virginia","coordinates":[-76.88017,37.11976]}, {"dem":743,"rep":3370,"total":4223,"name":"Heard, Georgia","coordinates":[-85.13788,33.29134]}, {"dem":2857,"rep":1318,"total":4218,"name":"Wilkinson, Mississippi","coordinates":[-91.32461,31.16109]}, {"dem":1185,"rep":2911,"total":4216,"name":"Deaf Smith, Texas","coordinates":[-102.60756,34.94076]}, {"dem":2058,"rep":1763,"total":4206,"name":"Deer Lodge, Montana","coordinates":[-113.14162,46.09467]}, {"dem":1145,"rep":2965,"total":4198,"name":"Karnes, Texas","coordinates":[-97.8522,28.90899]}, {"dem":2267,"rep":1874,"total":4189,"name":"Terrell, Georgia","coordinates":[-84.43944,31.77719]}, {"dem":770,"rep":3103,"total":4185,"name":"Benewah, Idaho","coordinates":[-116.63354,47.21845]}, {"dem":1554,"rep":2468,"total":4185,"name":"Pecos, Texas","coordinates":[-102.71815,30.77329]}, {"dem":442,"rep":2827,"total":4177,"name":"Juab, Utah","coordinates":[-112.79047,39.71412]}, {"dem":2350,"rep":1716,"total":4176,"name":"Chicot, Arkansas","coordinates":[-91.29715,33.26713]}, {"dem":768,"rep":3283,"total":4168,"name":"Graham, North Carolina","coordinates":[-83.83091,35.34836]}, {"dem":2783,"rep":1316,"total":4168,"name":"Duval, Texas","coordinates":[-98.49739,27.68112]}, {"dem":1017,"rep":2721,"total":4167,"name":"Morrow, Oregon","coordinates":[-119.60231,45.42549]}, {"dem":802,"rep":3206,"total":4166,"name":"Hamilton, Illinois","coordinates":[-88.539,38.08522]}, {"dem":853,"rep":3159,"total":4156,"name":"Monroe, Missouri","coordinates":[-92.00645,39.49826]}, {"dem":1369,"rep":2556,"total":4154,"name":"Schoolcraft, Michigan","coordinates":[-86.19702,46.02112]}, {"dem":961,"rep":2937,"total":4150,"name":"Turner, South Dakota","coordinates":[-97.15018,43.30866]}, {"dem":1360,"rep":2626,"total":4117,"name":"Long, Georgia","coordinates":[-81.74286,31.74956]}, {"dem":720,"rep":3188,"total":4115,"name":"Knox, Nebraska","coordinates":[-97.89134,42.6344]}, {"dem":2094,"rep":1487,"total":4110,"name":"Grand Isle, Vermont","coordinates":[-73.30075,44.80178]}, {"dem":2496,"rep":1476,"total":4107,"name":"Charles City, Virginia","coordinates":[-77.05417,37.36105]}, {"dem":1220,"rep":2582,"total":4106,"name":"Mountrail, North Dakota","coordinates":[-102.36489,48.21007]}, {"dem":809,"rep":3166,"total":4105,"name":"Wilbarger, Texas","coordinates":[-99.24243,34.08491]}, {"dem":1273,"rep":2759,"total":4102,"name":"Lincoln, Georgia","coordinates":[-82.44829,33.79215]}, {"dem":816,"rep":3161,"total":4101,"name":"Ballard, Kentucky","coordinates":[-89.01036,37.05132]}, {"dem":733,"rep":3011,"total":4096,"name":"Lemhi, Idaho","coordinates":[-113.88704,44.9285]}, {"dem":496,"rep":3405,"total":4075,"name":"Ritchie, West Virginia","coordinates":[-81.06631,39.17711]}, {"dem":719,"rep":3122,"total":4074,"name":"Cuming, Nebraska","coordinates":[-96.78851,41.91586]}, {"dem":1044,"rep":2843,"total":4073,"name":"Oscoda, Michigan","coordinates":[-84.1269,44.68725]}, {"dem":727,"rep":3050,"total":4068,"name":"Coffey, Kansas","coordinates":[-95.72913,38.23645]}, {"dem":1218,"rep":2788,"total":4065,"name":"Choctaw, Mississippi","coordinates":[-89.25133,33.34596]}, {"dem":1971,"rep":2035,"total":4059,"name":"Twiggs, Georgia","coordinates":[-83.42587,32.66584]}, {"dem":797,"rep":3100,"total":4056,"name":"Latimer, Oklahoma","coordinates":[-95.27226,34.87513]}, {"dem":617,"rep":3290,"total":4037,"name":"Crittenden, Kentucky","coordinates":[-88.10501,37.35814]}, {"dem":863,"rep":2906,"total":4036,"name":"Brown, Kansas","coordinates":[-95.5699,39.82593]}, {"dem":571,"rep":3235,"total":4034,"name":"Keith, Nebraska","coordinates":[-101.64444,41.19424]}, {"dem":1771,"rep":1914,"total":4022,"name":"Conejos, Colorado","coordinates":[-106.17644,37.2134]}, {"dem":608,"rep":3364,"total":4020,"name":"Bacon, Georgia","coordinates":[-82.45143,31.5502]}, {"dem":786,"rep":3093,"total":4018,"name":"Johnston, Oklahoma","coordinates":[-96.65425,34.31345]}, {"dem":1004,"rep":2951,"total":4016,"name":"Charlton, Georgia","coordinates":[-82.13964,30.7799]}, {"dem":1719,"rep":2251,"total":4013,"name":"Benton, Mississippi","coordinates":[-89.20028,34.81051]}, {"dem":771,"rep":3111,"total":3995,"name":"Lamb, Texas","coordinates":[-102.34801,34.06886]}, {"dem":685,"rep":3150,"total":3981,"name":"Pike, Arkansas","coordinates":[-93.65865,34.15819]}, {"dem":691,"rep":3079,"total":3981,"name":"Butler, Nebraska","coordinates":[-97.13203,41.22607]}, {"dem":683,"rep":2912,"total":3974,"name":"Harney, Oregon","coordinates":[-118.98716,43.06444]}, {"dem":888,"rep":2950,"total":3969,"name":"Chariton, Missouri","coordinates":[-92.96162,39.51796]}, {"dem":1045,"rep":2789,"total":3962,"name":"Lyon, Kentucky","coordinates":[-88.08339,37.02397]}, {"dem":363,"rep":3503,"total":3953,"name":"Martin, Kentucky","coordinates":[-82.50662,37.79677]}, {"dem":637,"rep":3184,"total":3951,"name":"Dade, Missouri","coordinates":[-93.85487,37.43234]}, {"dem":943,"rep":2800,"total":3943,"name":"Okfuskee, Oklahoma","coordinates":[-96.32776,35.4668]}, {"dem":1241,"rep":2265,"total":3933,"name":"Traill, North Dakota","coordinates":[-97.16475,47.44621]}, {"dem":839,"rep":2898,"total":3930,"name":"Warren, Indiana","coordinates":[-87.37584,40.35265]}, {"dem":761,"rep":2919,"total":3930,"name":"Cloud, Kansas","coordinates":[-97.64138,39.48732]}, {"dem":639,"rep":3022,"total":3930,"name":"Lake, Oregon","coordinates":[-120.38978,42.7884]}, {"dem":591,"rep":3052,"total":3925,"name":"Owyhee, Idaho","coordinates":[-116.18969,42.57285]}, {"dem":776,"rep":2966,"total":3904,"name":"Shannon, Missouri","coordinates":[-91.39132,37.15249]}, {"dem":541,"rep":3206,"total":3897,"name":"Somervell, Texas","coordinates":[-97.76921,32.21807]}, {"dem":886,"rep":2698,"total":3894,"name":"Valley, Montana","coordinates":[-106.67042,48.34984]}, {"dem":1540,"rep":2144,"total":3889,"name":"Roberts, South Dakota","coordinates":[-96.94755,45.62339]}, {"dem":977,"rep":2723,"total":3882,"name":"Davis, Iowa","coordinates":[-92.41034,40.74808]}, {"dem":1056,"rep":2638,"total":3865,"name":"Monroe, Iowa","coordinates":[-92.86964,41.02884]}, {"dem":963,"rep":2702,"total":3865,"name":"Pocahontas, Iowa","coordinates":[-94.67827,42.73403]}, {"dem":1305,"rep":2293,"total":3860,"name":"Lac Qui Parle, Minnesota","coordinates":[-96.17683,44.99985]}, {"dem":3337,"rep":490,"total":3860,"name":"Jefferson, Mississippi","coordinates":[-91.04387,31.73363]}, {"dem":1872,"rep":1951,"total":3859,"name":"Dooly, Georgia","coordinates":[-83.80716,32.15199]}, {"dem":1106,"rep":2588,"total":3855,"name":"Carroll, Kentucky","coordinates":[-85.12402,38.66839]}, {"dem":771,"rep":2838,"total":3842,"name":"Pratt, Kansas","coordinates":[-98.74011,37.64759]}, {"dem":1075,"rep":2524,"total":3828,"name":"Schuyler, Illinois","coordinates":[-90.61346,40.1569]}, {"dem":1252,"rep":2455,"total":3826,"name":"Lincoln, Arkansas","coordinates":[-91.72762,33.95767]}, {"dem":273,"rep":3348,"total":3826,"name":"Crook, Wyoming","coordinates":[-104.56729,44.58926]}, {"dem":677,"rep":2891,"total":3820,"name":"Clay, Kansas","coordinates":[-97.16885,39.34496]}, {"dem":777,"rep":2673,"total":3814,"name":"Boise, Idaho","coordinates":[-115.71511,43.98727]}, {"dem":532,"rep":2911,"total":3814,"name":"Washakie, Wyoming","coordinates":[-107.66905,43.87883]}, {"dem":1133,"rep":2461,"total":3811,"name":"Adair, Iowa","coordinates":[-94.47816,41.32852]}, {"dem":818,"rep":2769,"total":3805,"name":"Richardson, Nebraska","coordinates":[-95.7186,40.12374]}, {"dem":695,"rep":2837,"total":3804,"name":"Rice, Kansas","coordinates":[-98.20141,38.34717]}, {"dem":704,"rep":2852,"total":3801,"name":"Clearwater, Idaho","coordinates":[-115.6535,46.67257]}, {"dem":879,"rep":2771,"total":3798,"name":"Trimble, Kentucky","coordinates":[-85.3512,38.62004]}, {"dem":1313,"rep":2450,"total":3796,"name":"Telfair, Georgia","coordinates":[-82.93106,31.91364]}, {"dem":711,"rep":2884,"total":3793,"name":"Blaine, Oklahoma","coordinates":[-98.42893,35.87778]}, {"dem":735,"rep":2922,"total":3789,"name":"Love, Oklahoma","coordinates":[-97.24509,33.9578]}, {"dem":877,"rep":2696,"total":3788,"name":"Modoc, California","coordinates":[-120.71837,41.59291]}, {"dem":602,"rep":2926,"total":3788,"name":"Merrick, Nebraska","coordinates":[-98.03105,41.16978]}, {"dem":1633,"rep":1883,"total":3783,"name":"Huerfano, Colorado","coordinates":[-104.95992,37.68781]}, {"dem":453,"rep":3250,"total":3782,"name":"Runnels, Texas","coordinates":[-99.98271,31.84511]}, {"dem":835,"rep":2693,"total":3776,"name":"Wayne, Nebraska","coordinates":[-97.12624,42.21074]}, {"dem":707,"rep":2723,"total":3773,"name":"White Pine, Nevada","coordinates":[-114.9006,39.41823]}, {"dem":1026,"rep":2664,"total":3763,"name":"Candler, Georgia","coordinates":[-82.07126,32.40394]}, {"dem":2099,"rep":1217,"total":3755,"name":"Rolette, North Dakota","coordinates":[-99.84046,48.76827]}, {"dem":699,"rep":2875,"total":3753,"name":"Newton, Arkansas","coordinates":[-93.21589,35.91074]}, {"dem":1345,"rep":2206,"total":3739,"name":"Pepin, Wisconsin","coordinates":[-91.83488,44.62743]}, {"dem":1201,"rep":2296,"total":3734,"name":"Decatur, Iowa","coordinates":[-93.78457,40.73637]}, {"dem":601,"rep":2955,"total":3728,"name":"Searcy, Arkansas","coordinates":[-92.69588,35.89638]}, {"dem":973,"rep":2620,"total":3708,"name":"Goliad, Texas","coordinates":[-97.43041,28.6607]}, {"dem":536,"rep":2967,"total":3702,"name":"Kit Carson, Colorado","coordinates":[-102.60302,39.30533]}, {"dem":930,"rep":2558,"total":3699,"name":"Switzerland, Indiana","coordinates":[-85.02968,38.82585]}, {"dem":1468,"rep":2099,"total":3697,"name":"King and Queen, Virginia","coordinates":[-76.90558,37.71777]}, {"dem":323,"rep":3256,"total":3692,"name":"Cameron, Louisiana","coordinates":[-93.16494,29.87181]}, {"dem":574,"rep":2965,"total":3689,"name":"Harrison, Missouri","coordinates":[-93.99258,40.34562]}, {"dem":1136,"rep":2519,"total":3686,"name":"Johnson, Georgia","coordinates":[-82.66396,32.69458]}, {"dem":801,"rep":2632,"total":3676,"name":"Dawes, Nebraska","coordinates":[-103.13487,42.71121]}, {"dem":891,"rep":2716,"total":3670,"name":"Irwin, Georgia","coordinates":[-83.27703,31.6043]}, {"dem":522,"rep":2947,"total":3668,"name":"Woods, Oklahoma","coordinates":[-98.86364,36.72698]}, {"dem":860,"rep":2579,"total":3666,"name":"Benton, Indiana","coordinates":[-87.31478,40.60093]}, {"dem":507,"rep":2996,"total":3654,"name":"Tyler, West Virginia","coordinates":[-80.87721,39.46563]}, {"dem":1317,"rep":2164,"total":3653,"name":"Bradley, Arkansas","coordinates":[-92.16915,33.46654]}, {"dem":1560,"rep":1797,"total":3652,"name":"Roosevelt, Montana","coordinates":[-104.99516,48.28274]}, {"dem":928,"rep":2496,"total":3646,"name":"Pocahontas, West Virginia","coordinates":[-80.01012,38.3326]}, {"dem":388,"rep":3177,"total":3643,"name":"Coleman, Texas","coordinates":[-99.34662,31.9142]}, {"dem":382,"rep":3052,"total":3630,"name":"Pierce, Nebraska","coordinates":[-97.61099,42.27141]}, {"dem":479,"rep":3060,"total":3620,"name":"Hamilton, Texas","coordinates":[-98.11175,31.70734]}, {"dem":1130,"rep":2404,"total":3613,"name":"Evans, Georgia","coordinates":[-81.89015,32.15308]}, {"dem":792,"rep":2655,"total":3612,"name":"Ida, Iowa","coordinates":[-95.50742,42.39186]}, {"dem":1104,"rep":2437,"total":3605,"name":"Pulaski, Georgia","coordinates":[-83.48184,32.2388]}, {"dem":1098,"rep":2202,"total":3601,"name":"Ferry, Washington","coordinates":[-118.53358,48.47325]}, {"dem":963,"rep":2407,"total":3595,"name":"Fremont, Iowa","coordinates":[-95.59918,40.74259]}, {"dem":730,"rep":2767,"total":3593,"name":"Daviess, Missouri","coordinates":[-93.97005,39.96283]}, {"dem":2735,"rep":789,"total":3592,"name":"Allendale, South Carolina","coordinates":[-81.36326,32.97975]}, {"dem":594,"rep":2788,"total":3591,"name":"Wilson, Kansas","coordinates":[-95.74517,37.55851]}, {"dem":1189,"rep":2345,"total":3588,"name":"Seminole, Georgia","coordinates":[-84.86768,30.93395]}, {"dem":2701,"rep":843,"total":3580,"name":"Hancock, Georgia","coordinates":[-83.00046,33.26921]}, {"dem":1634,"rep":1566,"total":3576,"name":"Gilpin, Colorado","coordinates":[-105.52887,39.86115]}, {"dem":847,"rep":2670,"total":3576,"name":"Montgomery, Georgia","coordinates":[-82.53334,32.1721]}, {"dem":473,"rep":2908,"total":3576,"name":"Thomas, Kansas","coordinates":[-101.08338,39.35771]}, {"dem":1017,"rep":2212,"total":3572,"name":"Quay, New Mexico","coordinates":[-103.54807,35.10701]}, {"dem":910,"rep":2622,"total":3569,"name":"San Augustine, Texas","coordinates":[-94.16317,31.38244]}, {"dem":2667,"rep":853,"total":3567,"name":"Tunica, Mississippi","coordinates":[-90.37176,34.6522]}, {"dem":971,"rep":2382,"total":3564,"name":"Grant, South Dakota","coordinates":[-96.77226,45.17263]}, {"dem":821,"rep":2511,"total":3563,"name":"Fall River, South Dakota","coordinates":[-103.5126,43.22161]}, {"dem":835,"rep":2636,"total":3563,"name":"Dawson, Texas","coordinates":[-101.94877,32.74252]}, {"dem":845,"rep":2527,"total":3561,"name":"Van Buren, Iowa","coordinates":[-91.95294,40.75411]}, {"dem":748,"rep":2643,"total":3559,"name":"Montgomery, Arkansas","coordinates":[-93.66415,34.54565]}, {"dem":930,"rep":2367,"total":3558,"name":"Burt, Nebraska","coordinates":[-96.33774,41.85417]}, {"dem":705,"rep":2711,"total":3527,"name":"Bracken, Kentucky","coordinates":[-84.11523,38.68036]}, {"dem":299,"rep":3033,"total":3526,"name":"Weston, Wyoming","coordinates":[-104.57002,43.84621]}, {"dem":1155,"rep":2155,"total":3518,"name":"Henderson, Illinois","coordinates":[-90.94124,40.81447]}, {"dem":602,"rep":2731,"total":3510,"name":"Scott, Arkansas","coordinates":[-94.06364,34.85886]}, {"dem":741,"rep":2265,"total":3505,"name":"Kane, Utah","coordinates":[-111.81532,37.27508]}, {"dem":1273,"rep":2090,"total":3497,"name":"Iron, Wisconsin","coordinates":[-90.26129,46.32655]}, {"dem":837,"rep":2399,"total":3494,"name":"Jefferson, Nebraska","coordinates":[-97.1431,40.17573]}, {"dem":736,"rep":2494,"total":3494,"name":"Bottineau, North Dakota","coordinates":[-100.83125,48.79441]}, {"dem":767,"rep":2596,"total":3493,"name":"Kiowa, Oklahoma","coordinates":[-98.98161,34.92148]}, {"dem":1156,"rep":2158,"total":3490,"name":"Baraga, Michigan","coordinates":[-88.36181,46.69585]}, {"dem":751,"rep":2565,"total":3475,"name":"Tucker, West Virginia","coordinates":[-79.55996,39.11117]}, {"dem":1105,"rep":2063,"total":3473,"name":"Grant, Minnesota","coordinates":[-96.01069,45.93074]}, {"dem":348,"rep":3034,"total":3461,"name":"Stephens, Texas","coordinates":[-98.83934,32.73805]}, {"dem":987,"rep":2253,"total":3453,"name":"Rosebud, Montana","coordinates":[-106.66674,46.17323]}, {"dem":436,"rep":2791,"total":3450,"name":"Rio Blanco, Colorado","coordinates":[-108.20071,39.97262]}, {"dem":783,"rep":2547,"total":3445,"name":"Ward, Texas","coordinates":[-103.10511,31.51306]}, {"dem":814,"rep":2505,"total":3444,"name":"Prairie, Arkansas","coordinates":[-91.55362,34.83111]}, {"dem":935,"rep":2382,"total":3433,"name":"Charles Mix, South Dakota","coordinates":[-98.59514,43.20618]}, {"dem":1176,"rep":2066,"total":3426,"name":"Ontonagon, Michigan","coordinates":[-89.50046,47.2166]}, {"dem":1080,"rep":2136,"total":3412,"name":"Audubon, Iowa","coordinates":[-94.90431,41.67917]}, {"dem":1296,"rep":2064,"total":3408,"name":"Taylor, Georgia","coordinates":[-84.25142,32.55466]}, {"dem":310,"rep":2948,"total":3407,"name":"Major, Oklahoma","coordinates":[-98.54201,36.31311]}, {"dem":1246,"rep":2095,"total":3398,"name":"Turner, Georgia","coordinates":[-83.62031,31.7248]}, {"dem":2636,"rep":694,"total":3396,"name":"Zavala, Texas","coordinates":[-99.75983,28.86465]}, {"dem":1912,"rep":1156,"total":3395,"name":"Cook, Minnesota","coordinates":[-90.29018,47.53856]}, {"dem":518,"rep":2809,"total":3392,"name":"Lafayette, Florida","coordinates":[-83.1785,29.99006]}, {"dem":776,"rep":2372,"total":3380,"name":"Wabaunsee, Kansas","coordinates":[-96.20126,38.95515]}, {"dem":587,"rep":2606,"total":3378,"name":"Doniphan, Kansas","coordinates":[-95.14722,39.7885]}, {"dem":2312,"rep":1001,"total":3365,"name":"Quitman, Mississippi","coordinates":[-90.29017,34.25283]}, {"dem":692,"rep":2517,"total":3365,"name":"Hutchinson, South Dakota","coordinates":[-97.74938,43.33671]}, {"dem":753,"rep":2459,"total":3355,"name":"Terry, Texas","coordinates":[-102.33928,33.17122]}, {"dem":723,"rep":2462,"total":3354,"name":"Cleveland, Arkansas","coordinates":[-92.18871,33.8932]}, {"dem":672,"rep":2435,"total":3350,"name":"Anderson, Kansas","coordinates":[-95.29204,38.21511]}, {"dem":314,"rep":2973,"total":3350,"name":"Jack, Texas","coordinates":[-98.17117,33.23216]}, {"dem":434,"rep":2778,"total":3347,"name":"Edwards, Illinois","coordinates":[-88.04794,38.41709]}, {"dem":749,"rep":2443,"total":3338,"name":"Gallatin, Kentucky","coordinates":[-84.86215,38.7601]}, {"dem":599,"rep":2530,"total":3334,"name":"Kingman, Kansas","coordinates":[-98.14452,37.55295]}, {"dem":1697,"rep":1351,"total":3310,"name":"Ouray, Colorado","coordinates":[-107.78848,38.15473]}, {"dem":893,"rep":2129,"total":3302,"name":"Wilkin, Minnesota","coordinates":[-96.47665,46.36233]}, {"dem":651,"rep":2543,"total":3296,"name":"Liberty, Florida","coordinates":[-84.86858,30.25984]}, {"dem":550,"rep":2531,"total":3296,"name":"Kearney, Nebraska","coordinates":[-98.9476,40.50911]}, {"dem":715,"rep":2445,"total":3291,"name":"Union, Indiana","coordinates":[-84.92515,39.62311]}, {"dem":383,"rep":2732,"total":3281,"name":"Antelope, Nebraska","coordinates":[-98.05803,42.18322]}, {"dem":1092,"rep":1892,"total":3270,"name":"Greenlee, Arizona","coordinates":[-109.24232,33.23887]}, {"dem":1264,"rep":1699,"total":3261,"name":"Norman, Minnesota","coordinates":[-96.46377,47.32945]}, {"dem":606,"rep":2524,"total":3255,"name":"Shelby, Missouri","coordinates":[-92.08871,39.79753]}, {"dem":1157,"rep":2000,"total":3246,"name":"Nevada, Arkansas","coordinates":[-93.30507,33.66669]}, {"dem":2002,"rep":1196,"total":3246,"name":"Talbot, Georgia","coordinates":[-84.53002,32.7046]}, {"dem":949,"rep":2064,"total":3225,"name":"Hamilton, New York","coordinates":[-74.50245,43.65787]}, {"dem":2173,"rep":974,"total":3225,"name":"Dimmit, Texas","coordinates":[-99.76587,28.42358]}, {"dem":729,"rep":2398,"total":3225,"name":"Pendleton, West Virginia","coordinates":[-79.34061,38.67445]}, {"dem":724,"rep":2458,"total":3215,"name":"Clark, Missouri","coordinates":[-91.72947,40.40727]}, {"dem":859,"rep":2171,"total":3214,"name":"Colfax, Nebraska","coordinates":[-97.08894,41.57496]}, {"dem":552,"rep":2531,"total":3213,"name":"Osceola, Iowa","coordinates":[-95.63378,43.37854]}, {"dem":1616,"rep":1270,"total":3199,"name":"Lake, Colorado","coordinates":[-106.35007,39.20534]}, {"dem":461,"rep":2574,"total":3193,"name":"Russell, Kansas","coordinates":[-98.77094,38.91603]}, {"dem":1213,"rep":1921,"total":3190,"name":"Marion, Georgia","coordinates":[-84.52873,32.35931]}, {"dem":808,"rep":2170,"total":3188,"name":"Teton, Montana","coordinates":[-112.28172,47.81903]}, {"dem":1659,"rep":1417,"total":3184,"name":"Reeves, Texas","coordinates":[-103.7127,31.30836]}, {"dem":866,"rep":2182,"total":3168,"name":"Houston, Tennessee","coordinates":[-87.70559,36.28578]}, {"dem":785,"rep":2116,"total":3161,"name":"Nemaha, Nebraska","coordinates":[-95.85272,40.38738]}, {"dem":946,"rep":2103,"total":3160,"name":"Trousdale, Tennessee","coordinates":[-86.15669,36.39302]}, {"dem":681,"rep":2208,"total":3153,"name":"Pembina, North Dakota","coordinates":[-97.5454,48.76689]}, {"dem":621,"rep":2358,"total":3150,"name":"Pleasants, West Virginia","coordinates":[-81.16117,39.36813]}, {"dem":2063,"rep":1029,"total":3142,"name":"Zapata, Texas","coordinates":[-99.1826,26.99698]}, {"dem":453,"rep":2573,"total":3139,"name":"Bland, Virginia","coordinates":[-81.12585,37.13061]}, {"dem":750,"rep":2291,"total":3136,"name":"Sullivan, Pennsylvania","coordinates":[-76.51171,41.43928]}, {"dem":573,"rep":2348,"total":3133,"name":"Broadwater, Montana","coordinates":[-111.49787,46.32984]}, {"dem":317,"rep":2623,"total":3118,"name":"Cherry, Nebraska","coordinates":[-101.04765,42.57132]}, {"dem":1147,"rep":1767,"total":3111,"name":"Putnam, Illinois","coordinates":[-89.29834,41.19896]}, {"dem":482,"rep":2552,"total":3103,"name":"McCulloch, Texas","coordinates":[-99.35985,31.20547]}, {"dem":797,"rep":2061,"total":3066,"name":"Custer, Colorado","coordinates":[-105.37351,38.10199]}, {"dem":459,"rep":2502,"total":3066,"name":"Cumberland, Kentucky","coordinates":[-85.38848,36.78237]}, {"dem":477,"rep":2422,"total":3065,"name":"Clay, Nebraska","coordinates":[-98.05085,40.52366]}, {"dem":1123,"rep":1895,"total":3056,"name":"Jenkins, Georgia","coordinates":[-81.97152,32.79456]}, {"dem":605,"rep":2304,"total":3043,"name":"Gentry, Missouri","coordinates":[-94.40532,40.20812]}, {"dem":540,"rep":2406,"total":3038,"name":"Reynolds, Missouri","coordinates":[-90.97228,37.36646]}, {"dem":271,"rep":2275,"total":3035,"name":"Caribou, Idaho","coordinates":[-111.54427,42.78607]}, {"dem":758,"rep":2111,"total":3029,"name":"Taylor, Iowa","coordinates":[-94.6971,40.73794]}, {"dem":1735,"rep":1229,"total":3026,"name":"Lee, Arkansas","coordinates":[-90.77971,34.7795]}, {"dem":860,"rep":1931,"total":3019,"name":"Lincoln, Minnesota","coordinates":[-96.27203,44.40823]}, {"dem":274,"rep":2628,"total":3002,"name":"Ochiltree, Texas","coordinates":[-100.81586,36.27874]}, {"dem":544,"rep":2284,"total":2994,"name":"Howard, Nebraska","coordinates":[-98.51334,41.21685]}, {"dem":556,"rep":2302,"total":2978,"name":"Webster, West Virginia","coordinates":[-80.44905,38.48345]}, {"dem":852,"rep":2096,"total":2976,"name":"Wilcox, Georgia","coordinates":[-83.43825,31.96271]}, {"dem":704,"rep":2105,"total":2974,"name":"Bon Homme, South Dakota","coordinates":[-97.88419,42.98579]}, {"dem":568,"rep":2300,"total":2972,"name":"Clay, West Virginia","coordinates":[-81.08186,38.45982]}, {"dem":249,"rep":2620,"total":2964,"name":"Carson, Texas","coordinates":[-101.35535,35.40549]}, {"dem":919,"rep":1854,"total":2951,"name":"Spink, South Dakota","coordinates":[-98.33961,44.92377]}, {"dem":1034,"rep":1830,"total":2948,"name":"Refugio, Texas","coordinates":[-97.16247,28.32211]}, {"dem":477,"rep":2308,"total":2942,"name":"Mitchell, Kansas","coordinates":[-98.20736,39.39302]}, {"dem":613,"rep":2130,"total":2941,"name":"Fillmore, Nebraska","coordinates":[-97.5967,40.52503]}, {"dem":719,"rep":2069,"total":2940,"name":"Wayne, Iowa","coordinates":[-93.33261,40.73998]}, {"dem":1838,"rep":1059,"total":2939,"name":"East Carroll, Louisiana","coordinates":[-91.23414,32.73016]}, {"dem":1043,"rep":1731,"total":2933,"name":"Moody, South Dakota","coordinates":[-96.67605,44.01242]}, {"dem":255,"rep":2203,"total":2928,"name":"Bear Lake, Idaho","coordinates":[-111.32751,42.28589]}, {"dem":496,"rep":2325,"total":2926,"name":"Moore, Tennessee","coordinates":[-86.35868,35.28888]}, {"dem":1019,"rep":1506,"total":2925,"name":"Essex, Vermont","coordinates":[-71.73273,44.72402]}, {"dem":686,"rep":2118,"total":2921,"name":"Ohio, Indiana","coordinates":[-84.96429,38.94052]}, {"dem":707,"rep":2141,"total":2920,"name":"Clay, Tennessee","coordinates":[-85.54571,36.54574]}, {"dem":414,"rep":2299,"total":2905,"name":"Boone, Nebraska","coordinates":[-98.07047,41.70393]}, {"dem":424,"rep":2283,"total":2903,"name":"Ottawa, Kansas","coordinates":[-97.6548,39.13796]}, {"dem":1598,"rep":1271,"total":2899,"name":"Randolph, Georgia","coordinates":[-84.75231,31.76265]}, {"dem":1312,"rep":1489,"total":2884,"name":"Monroe, Arkansas","coordinates":[-91.2033,34.67951]}, {"dem":806,"rep":1984,"total":2871,"name":"Lanier, Georgia","coordinates":[-83.06316,31.03819]}, {"dem":1032,"rep":1758,"total":2860,"name":"Lafayette, Arkansas","coordinates":[-93.61151,33.24062]}, {"dem":740,"rep":2000,"total":2855,"name":"Elliott, Kentucky","coordinates":[-83.09611,38.11688]}, {"dem":597,"rep":2167,"total":2855,"name":"Perry, Tennessee","coordinates":[-87.86932,35.66375]}, {"dem":1262,"rep":1496,"total":2846,"name":"Alexander, Illinois","coordinates":[-89.34951,37.18365]}, {"dem":436,"rep":2324,"total":2844,"name":"Carter, Missouri","coordinates":[-90.9457,36.94485]}, {"dem":787,"rep":1957,"total":2841,"name":"Nicholas, Kentucky","coordinates":[-84.02622,38.33803]}, {"dem":485,"rep":2160,"total":2840,"name":"Greenwood, Kansas","coordinates":[-96.24173,37.87934]}, {"dem":362,"rep":2358,"total":2840,"name":"Doddridge, West Virginia","coordinates":[-80.70123,39.26348]}, {"dem":1417,"rep":1147,"total":2835,"name":"Saguache, Colorado","coordinates":[-106.23466,38.03165]}, {"dem":490,"rep":2050,"total":2820,"name":"McHenry, North Dakota","coordinates":[-100.63326,48.23384]}, {"dem":417,"rep":2187,"total":2801,"name":"Stanton, Nebraska","coordinates":[-97.1771,41.90504]}, {"dem":551,"rep":2029,"total":2794,"name":"Powell, Montana","coordinates":[-112.93109,46.84422]}, {"dem":541,"rep":2140,"total":2794,"name":"Craig, Virginia","coordinates":[-80.23105,37.4736]}, {"dem":556,"rep":2041,"total":2782,"name":"Dixon, Nebraska","coordinates":[-96.85586,42.48528]}, {"dem":700,"rep":2010,"total":2779,"name":"Menifee, Kentucky","coordinates":[-83.58936,37.9355]}, {"dem":1165,"rep":1509,"total":2771,"name":"Dallas, Arkansas","coordinates":[-92.65399,33.96782]}, {"dem":387,"rep":2194,"total":2765,"name":"Washington, Kansas","coordinates":[-97.09561,39.77671]}, {"dem":555,"rep":2051,"total":2762,"name":"Hamlin, South Dakota","coordinates":[-97.17859,44.68061]}, {"dem":699,"rep":1666,"total":2758,"name":"Power, Idaho","coordinates":[-112.8444,42.69412]}, {"dem":921,"rep":1608,"total":2755,"name":"Big Stone, Minnesota","coordinates":[-96.40222,45.41992]}, {"dem":974,"rep":1627,"total":2747,"name":"Day, South Dakota","coordinates":[-97.58142,45.35516]}, {"dem":751,"rep":1778,"total":2743,"name":"Stark, Illinois","coordinates":[-89.79741,41.0969]}, {"dem":962,"rep":1675,"total":2735,"name":"Pulaski, Illinois","coordinates":[-89.12775,37.21561]}, {"dem":296,"rep":2299,"total":2733,"name":"Washington, Colorado","coordinates":[-103.20974,39.96578]}, {"dem":541,"rep":2060,"total":2724,"name":"Atchison, Missouri","coordinates":[-95.43755,40.43184]}, {"dem":738,"rep":1799,"total":2723,"name":"Pondera, Montana","coordinates":[-112.22076,48.2286]}, {"dem":657,"rep":1942,"total":2707,"name":"Gallatin, Illinois","coordinates":[-88.22796,37.76867]}, {"dem":753,"rep":1824,"total":2707,"name":"Ringgold, Iowa","coordinates":[-94.24425,40.73533]}, {"dem":657,"rep":1944,"total":2706,"name":"Tillman, Oklahoma","coordinates":[-98.9317,34.37108]}, {"dem":862,"rep":1809,"total":2703,"name":"Treutlen, Georgia","coordinates":[-82.57088,32.40958]}, {"dem":499,"rep":2051,"total":2690,"name":"Thayer, Nebraska","coordinates":[-97.59626,40.17384]}, {"dem":1202,"rep":1268,"total":2684,"name":"Blaine, Montana","coordinates":[-108.96764,48.42828]}, {"dem":521,"rep":1969,"total":2679,"name":"Ellsworth, Kansas","coordinates":[-98.20535,38.70084]}, {"dem":444,"rep":2151,"total":2667,"name":"Lee, Kentucky","coordinates":[-83.71924,37.60811]}, {"dem":300,"rep":2233,"total":2664,"name":"Phillips, Kansas","coordinates":[-99.34214,39.7845]}, {"dem":579,"rep":1904,"total":2661,"name":"Pawnee, Kansas","coordinates":[-99.23477,38.18147]}, {"dem":666,"rep":1897,"total":2657,"name":"Florence, Wisconsin","coordinates":[-88.40698,45.87182]}, {"dem":753,"rep":1804,"total":2635,"name":"Wolfe, Kentucky","coordinates":[-83.4951,37.74389]}, {"dem":462,"rep":2069,"total":2630,"name":"Tripp, South Dakota","coordinates":[-99.87621,43.34972]}, {"dem":601,"rep":1820,"total":2624,"name":"Morris, Kansas","coordinates":[-96.65144,38.6882]}, {"dem":456,"rep":2035,"total":2617,"name":"Calhoun, West Virginia","coordinates":[-81.11547,38.84415]}, {"dem":536,"rep":2021,"total":2615,"name":"Pickett, Tennessee","coordinates":[-85.07574,36.55936]}, {"dem":347,"rep":2089,"total":2612,"name":"Sherman, Kansas","coordinates":[-101.71985,39.35135]}, {"dem":697,"rep":1878,"total":2610,"name":"Atkinson, Georgia","coordinates":[-82.87815,31.2968]}, {"dem":535,"rep":1966,"total":2608,"name":"Scott, Illinois","coordinates":[-90.47777,39.637]}, {"dem":287,"rep":2211,"total":2608,"name":"Sheridan, Nebraska","coordinates":[-102.36827,42.51228]}, {"dem":732,"rep":1679,"total":2603,"name":"Chouteau, Montana","coordinates":[-110.4362,47.88683]}, {"dem":424,"rep":2054,"total":2602,"name":"Cotton, Oklahoma","coordinates":[-98.37343,34.29067]}, {"dem":432,"rep":2094,"total":2601,"name":"Carlisle, Kentucky","coordinates":[-88.97661,36.85718]}, {"dem":1937,"rep":613,"total":2596,"name":"Brooks, Texas","coordinates":[-98.21527,27.03499]}, {"dem":623,"rep":1794,"total":2587,"name":"McCook, South Dakota","coordinates":[-97.35804,43.68041]}, {"dem":400,"rep":1939,"total":2586,"name":"Hot Springs, Wyoming","coordinates":[-108.43507,43.7202]}, {"dem":413,"rep":2028,"total":2582,"name":"Polk, Nebraska","coordinates":[-97.57066,41.18792]}, {"dem":681,"rep":1756,"total":2579,"name":"Luce, Michigan","coordinates":[-85.58236,46.9406]}, {"dem":393,"rep":1996,"total":2578,"name":"Harper, Kansas","coordinates":[-98.06659,37.18818]}, {"dem":1118,"rep":1347,"total":2571,"name":"Woodruff, Arkansas","coordinates":[-91.24453,35.19277]}, {"dem":739,"rep":1721,"total":2571,"name":"Calhoun, Illinois","coordinates":[-90.66629,39.16426]}, {"dem":752,"rep":1616,"total":2558,"name":"Storey, Nevada","coordinates":[-119.52464,39.43838]}, {"dem":703,"rep":1680,"total":2551,"name":"Kingsbury, South Dakota","coordinates":[-97.49931,44.36296]}, {"dem":1332,"rep":1182,"total":2548,"name":"Tensas, Louisiana","coordinates":[-91.34257,32.00148]}, {"dem":623,"rep":1891,"total":2544,"name":"Miller, Georgia","coordinates":[-84.73039,31.16293]}, {"dem":545,"rep":1896,"total":2543,"name":"Gilmer, West Virginia","coordinates":[-80.84941,38.91586]}, {"dem":375,"rep":2024,"total":2529,"name":"Republic, Kansas","coordinates":[-97.65088,39.8289]}, {"dem":264,"rep":1838,"total":2491,"name":"Beaver, Utah","coordinates":[-113.23894,38.35753]}, {"dem":526,"rep":1884,"total":2486,"name":"Sullivan, Missouri","coordinates":[-93.10978,40.20958]}, {"dem":457,"rep":1896,"total":2477,"name":"Walworth, South Dakota","coordinates":[-100.02785,45.4276]}, {"dem":485,"rep":1915,"total":2466,"name":"Parmer, Texas","coordinates":[-102.78485,34.53216]}, {"dem":1514,"rep":766,"total":2465,"name":"Lexington, Virginia","coordinates":[-79.44431,37.78233]}, {"dem":686,"rep":1727,"total":2455,"name":"Clinch, Georgia","coordinates":[-82.70261,30.91765]}, {"dem":332,"rep":1967,"total":2441,"name":"Musselshell, Montana","coordinates":[-108.43976,46.50528]}, {"dem":1536,"rep":665,"total":2441,"name":"Mora, New Mexico","coordinates":[-104.92189,35.98284]}, {"dem":409,"rep":1892,"total":2436,"name":"Lincoln, Colorado","coordinates":[-103.50755,38.99374]}, {"dem":386,"rep":1911,"total":2422,"name":"Wirt, West Virginia","coordinates":[-81.38297,39.02003]}, {"dem":275,"rep":2031,"total":2419,"name":"Rooks, Kansas","coordinates":[-99.32449,39.346]}, {"dem":539,"rep":1820,"total":2419,"name":"Van Buren, Tennessee","coordinates":[-85.4584,35.69923]}, {"dem":427,"rep":1777,"total":2414,"name":"Custer, Idaho","coordinates":[-114.25226,44.27335]}, {"dem":403,"rep":1828,"total":2413,"name":"Lander, Nevada","coordinates":[-117.04723,39.90021]}, {"dem":554,"rep":1667,"total":2407,"name":"Dickey, North Dakota","coordinates":[-98.49651,46.10775]}, {"dem":693,"rep":1430,"total":2407,"name":"Buena Vista, Virginia","coordinates":[-79.35813,37.72934]}, {"dem":626,"rep":1683,"total":2401,"name":"Forest, Pennsylvania","coordinates":[-79.2497,41.5133]}, {"dem":411,"rep":1898,"total":2399,"name":"Coal, Oklahoma","coordinates":[-96.28803,34.58286]}, {"dem":441,"rep":1804,"total":2389,"name":"Grant, Kansas","coordinates":[-101.29936,37.54753]}, {"dem":823,"rep":1349,"total":2385,"name":"Kittson, Minnesota","coordinates":[-96.78034,48.77604]}, {"dem":419,"rep":1796,"total":2383,"name":"Wells, North Dakota","coordinates":[-99.68221,47.58085]}, {"dem":774,"rep":1549,"total":2382,"name":"Fulton, Kentucky","coordinates":[-89.18765,36.55251]}, {"dem":914,"rep":1349,"total":2382,"name":"Covington, Virginia","coordinates":[-79.98543,37.78106]}, {"dem":476,"rep":1796,"total":2379,"name":"Brown, Illinois","coordinates":[-90.7503,39.96206]}, {"dem":681,"rep":1603,"total":2376,"name":"Galax, Virginia","coordinates":[-80.9143,36.66563]}, {"dem":1530,"rep":789,"total":2367,"name":"Emporia, Virginia","coordinates":[-77.53597,36.69618]}, {"dem":838,"rep":1210,"total":2359,"name":"Ransom, North Dakota","coordinates":[-97.64755,46.44927]}, {"dem":832,"rep":1344,"total":2358,"name":"Wahkiakum, Washington","coordinates":[-123.42445,46.29463]}, {"dem":293,"rep":2025,"total":2357,"name":"San Saba, Texas","coordinates":[-98.81929,31.15513]}, {"dem":347,"rep":1926,"total":2355,"name":"Holt, Missouri","coordinates":[-95.21907,40.09572]}, {"dem":365,"rep":1910,"total":2350,"name":"Jefferson, Oklahoma","coordinates":[-97.83888,34.10508]}, {"dem":353,"rep":1936,"total":2346,"name":"Putnam, Missouri","coordinates":[-93.01453,40.4786]}, {"dem":358,"rep":1606,"total":2344,"name":"Garfield, Utah","coordinates":[-111.4509,37.83166]}, {"dem":304,"rep":1921,"total":2340,"name":"Furnas, Nebraska","coordinates":[-99.90966,40.19186]}, {"dem":1314,"rep":991,"total":2334,"name":"Warren, Georgia","coordinates":[-82.68801,33.41916]}, {"dem":436,"rep":1791,"total":2332,"name":"Phillips, Colorado","coordinates":[-102.3451,40.59471]}, {"dem":194,"rep":2087,"total":2306,"name":"Wheeler, Texas","coordinates":[-100.2531,35.39259]}, {"dem":965,"rep":1288,"total":2304,"name":"Hyde, North Carolina","coordinates":[-76.15368,35.40815]}, {"dem":426,"rep":1797,"total":2303,"name":"Yoakum, Texas","coordinates":[-102.83224,33.16239]}, {"dem":571,"rep":1565,"total":2288,"name":"Brule, South Dakota","coordinates":[-99.0929,43.72987]}, {"dem":400,"rep":1836,"total":2281,"name":"Delta, Texas","coordinates":[-95.67335,33.38593]}, {"dem":639,"rep":1556,"total":2269,"name":"Calhoun, Arkansas","coordinates":[-92.51387,33.56046]}, {"dem":216,"rep":1933,"total":2258,"name":"Alfalfa, Oklahoma","coordinates":[-98.32344,36.7297]}, {"dem":603,"rep":1548,"total":2253,"name":"Bath, Virginia","coordinates":[-79.7312,38.06836]}, {"dem":286,"rep":1850,"total":2252,"name":"Barber, Kansas","coordinates":[-98.68505,37.2229]}, {"dem":222,"rep":1965,"total":2248,"name":"Dewey, Oklahoma","coordinates":[-99.01438,35.97795]}, {"dem":243,"rep":1951,"total":2245,"name":"Mills, Texas","coordinates":[-98.59462,31.49488]}, {"dem":358,"rep":1771,"total":2243,"name":"Dunn, North Dakota","coordinates":[-102.61232,47.35455]}, {"dem":176,"rep":1993,"total":2243,"name":"Beaver, Oklahoma","coordinates":[-100.48305,36.74833]}, {"dem":553,"rep":1540,"total":2242,"name":"Lake of the Woods, Minnesota","coordinates":[-94.90463,48.7681]}, {"dem":281,"rep":1840,"total":2234,"name":"Norton, Kansas","coordinates":[-99.89923,39.78386]}, {"dem":322,"rep":1843,"total":2231,"name":"Hancock, Tennessee","coordinates":[-83.22749,36.52135]}, {"dem":284,"rep":1802,"total":2209,"name":"Morrill, Nebraska","coordinates":[-102.99059,41.7322]}, {"dem":1458,"rep":652,"total":2208,"name":"Presidio, Texas","coordinates":[-104.26161,30.00589]}, {"dem":339,"rep":1780,"total":2205,"name":"Valley, Nebraska","coordinates":[-98.98348,41.56409]}, {"dem":353,"rep":1726,"total":2205,"name":"Nuckolls, Nebraska","coordinates":[-98.04684,40.17649]}, {"dem":462,"rep":1671,"total":2204,"name":"Swisher, Texas","coordinates":[-101.74386,34.52631]}, {"dem":236,"rep":1865,"total":2202,"name":"Scott, Kansas","coordinates":[-100.90636,38.48187]}, {"dem":288,"rep":1827,"total":2201,"name":"Grant, Oklahoma","coordinates":[-97.78815,36.78825]}, {"dem":354,"rep":1780,"total":2196,"name":"Mitchell, Texas","coordinates":[-100.92439,32.30411]}, {"dem":1479,"rep":692,"total":2190,"name":"Sharkey, Mississippi","coordinates":[-90.82761,32.89239]}, {"dem":531,"rep":1589,"total":2186,"name":"Cameron, Pennsylvania","coordinates":[-78.19832,41.43829]}, {"dem":415,"rep":1556,"total":2183,"name":"Adams, Idaho","coordinates":[-116.46162,44.877]}, {"dem":526,"rep":1497,"total":2182,"name":"Columbia, Washington","coordinates":[-117.91163,46.29285]}, {"dem":318,"rep":1723,"total":2171,"name":"Phillips, Montana","coordinates":[-107.92889,48.25014]}, {"dem":449,"rep":1657,"total":2157,"name":"Hickman, Kentucky","coordinates":[-88.97208,36.67589]}, {"dem":283,"rep":1753,"total":2153,"name":"Baca, Colorado","coordinates":[-102.54374,37.30978]}, {"dem":502,"rep":1481,"total":2151,"name":"LaMoure, North Dakota","coordinates":[-98.52605,46.46419]}, {"dem":420,"rep":1653,"total":2148,"name":"Hardin, Illinois","coordinates":[-88.26614,37.51785]}, {"dem":375,"rep":1678,"total":2142,"name":"Pope, Illinois","coordinates":[-88.54237,37.41716]}, {"dem":285,"rep":1671,"total":2132,"name":"Lincoln, Nevada","coordinates":[-114.86303,37.6346]}, {"dem":1505,"rep":487,"total":2125,"name":"Todd, South Dakota","coordinates":[-100.70766,43.20879]}, {"dem":1635,"rep":430,"total":2119,"name":"Jim Hogg, Texas","coordinates":[-98.74757,27.05323]}, {"dem":402,"rep":1595,"total":2107,"name":"Sweet Grass, Montana","coordinates":[-109.94479,45.81129]}, {"dem":565,"rep":1395,"total":2106,"name":"Adams, Iowa","coordinates":[-94.6969,41.02165]}, {"dem":646,"rep":1421,"total":2102,"name":"Wheeler, Georgia","coordinates":[-82.73384,32.10525]}, {"dem":391,"rep":1600,"total":2091,"name":"Gregory, South Dakota","coordinates":[-99.20659,43.17514]}, {"dem":563,"rep":1355,"total":2089,"name":"Johnson, Nebraska","coordinates":[-96.26536,40.395]}, {"dem":930,"rep":991,"total":2088,"name":"Mahnomen, Minnesota","coordinates":[-95.81108,47.32838]}, {"dem":919,"rep":1043,"total":2088,"name":"Thurston, Nebraska","coordinates":[-96.53394,42.15406]}, {"dem":253,"rep":1802,"total":2084,"name":"Childress, Texas","coordinates":[-100.20816,34.52462]}, {"dem":570,"rep":1366,"total":2080,"name":"Deuel, South Dakota","coordinates":[-96.69023,44.75628]}, {"dem":431,"rep":1437,"total":2071,"name":"Pierce, North Dakota","coordinates":[-99.96649,48.23888]}, {"dem":184,"rep":1531,"total":2068,"name":"Oneida, Idaho","coordinates":[-112.52044,42.18389]}, {"dem":263,"rep":1698,"total":2066,"name":"Gray, Kansas","coordinates":[-100.45171,37.74451]}, {"dem":1129,"rep":872,"total":2059,"name":"La Salle, Texas","coordinates":[-99.09677,28.35109]}, {"dem":1222,"rep":805,"total":2058,"name":"Stewart, Georgia","coordinates":[-84.83491,32.07322]}, {"dem":354,"rep":1656,"total":2057,"name":"Mason, Texas","coordinates":[-99.2373,30.70391]}, {"dem":427,"rep":1464,"total":2049,"name":"Catron, New Mexico","coordinates":[-108.39192,33.90162]}, {"dem":297,"rep":1661,"total":2042,"name":"Smith, Kansas","coordinates":[-98.78542,39.78466]}, {"dem":402,"rep":1497,"total":2037,"name":"Toole, Montana","coordinates":[-111.73347,48.64512]}, {"dem":1179,"rep":830,"total":2025,"name":"Calhoun, Georgia","coordinates":[-84.62628,31.52127]}, {"dem":519,"rep":1330,"total":2012,"name":"Mineral, Montana","coordinates":[-115.06562,47.15194]}, {"dem":842,"rep":929,"total":2011,"name":"Benson, North Dakota","coordinates":[-99.35115,48.07174]}, {"dem":403,"rep":1546,"total":2009,"name":"Lynn, Texas","coordinates":[-101.81849,33.17841]}, {"dem":476,"rep":1357,"total":2006,"name":"Cavalier, North Dakota","coordinates":[-98.46379,48.76843]}, {"dem":424,"rep":1497,"total":2006,"name":"Hanson, South Dakota","coordinates":[-97.79684,43.68061]}, {"dem":637,"rep":1179,"total":1997,"name":"Mineral, Nevada","coordinates":[-118.41627,38.51664]}, {"dem":694,"rep":1088,"total":1997,"name":"Sargent, North Dakota","coordinates":[-97.63005,46.1082]}, {"dem":526,"rep":1414,"total":1997,"name":"Castro, Texas","coordinates":[-102.25878,34.53362]}, {"dem":430,"rep":1403,"total":1982,"name":"Pershing, Nevada","coordinates":[-118.40947,40.43963]}, {"dem":215,"rep":1677,"total":1981,"name":"Emmons, North Dakota","coordinates":[-100.23784,46.28425]}, {"dem":577,"rep":1357,"total":1970,"name":"Lake, Tennessee","coordinates":[-89.48553,36.3339]}, {"dem":365,"rep":1525,"total":1968,"name":"Scotland, Missouri","coordinates":[-92.14282,40.44768]}, {"dem":435,"rep":1474,"total":1959,"name":"Floyd, Texas","coordinates":[-101.30327,34.07373]}, {"dem":173,"rep":1730,"total":1952,"name":"Hartley, Texas","coordinates":[-102.61004,35.84024]}, {"dem":206,"rep":1697,"total":1952,"name":"Kimble, Texas","coordinates":[-99.74639,30.47947]}, {"dem":754,"rep":1056,"total":1947,"name":"Marshall, South Dakota","coordinates":[-97.58086,45.73704]}, {"dem":171,"rep":1730,"total":1947,"name":"Hansford, Texas","coordinates":[-101.35693,36.27284]}, {"dem":354,"rep":1505,"total":1936,"name":"Schuyler, Missouri","coordinates":[-92.51901,40.46936]}, {"dem":590,"rep":1188,"total":1927,"name":"Bent, Colorado","coordinates":[-103.07758,37.93189]}, {"dem":380,"rep":1433,"total":1918,"name":"Edmunds, South Dakota","coordinates":[-99.20536,45.41168]}, {"dem":401,"rep":1472,"total":1909,"name":"Schley, Georgia","coordinates":[-84.3227,32.26344]}, {"dem":171,"rep":1648,"total":1898,"name":"Chase, Nebraska","coordinates":[-101.69419,40.53039]}, {"dem":304,"rep":1490,"total":1896,"name":"Stafford, Kansas","coordinates":[-98.71988,38.03563]}, {"dem":323,"rep":1482,"total":1896,"name":"Greer, Oklahoma","coordinates":[-99.55296,34.93385]}, {"dem":220,"rep":1599,"total":1891,"name":"Stevens, Kansas","coordinates":[-101.31726,37.2017]}, {"dem":540,"rep":1141,"total":1881,"name":"Red Lake, Minnesota","coordinates":[-96.08718,47.86548]}, {"dem":420,"rep":1403,"total":1876,"name":"Winkler, Texas","coordinates":[-103.05492,31.83286]}, {"dem":784,"rep":910,"total":1872,"name":"Hidalgo, New Mexico","coordinates":[-108.75192,31.89805]}, {"dem":379,"rep":1416,"total":1870,"name":"Knox, Missouri","coordinates":[-92.14683,40.13685]}, {"dem":1125,"rep":588,"total":1848,"name":"Costilla, Colorado","coordinates":[-105.42893,37.27754]}, {"dem":477,"rep":1241,"total":1835,"name":"Sheridan, Montana","coordinates":[-104.53391,48.70552]}, {"dem":254,"rep":1496,"total":1832,"name":"Harlan, Nebraska","coordinates":[-99.40341,40.17876]}, {"dem":601,"rep":1048,"total":1830,"name":"Sierra, California","coordinates":[-120.52199,39.57692]}, {"dem":970,"rep":595,"total":1827,"name":"Guadalupe, New Mexico","coordinates":[-104.78496,34.86978]}, {"dem":155,"rep":1611,"total":1827,"name":"Ellis, Oklahoma","coordinates":[-99.75013,36.22425]}, {"dem":334,"rep":1391,"total":1818,"name":"Hand, South Dakota","coordinates":[-99.00457,44.54671]}, {"dem":630,"rep":1049,"total":1798,"name":"Traverse, Minnesota","coordinates":[-96.47483,45.76993]}, {"dem":397,"rep":1344,"total":1793,"name":"Bailey, Texas","coordinates":[-102.83034,34.06752]}, {"dem":233,"rep":1460,"total":1788,"name":"Osborne, Kansas","coordinates":[-98.76794,39.34826]}, {"dem":227,"rep":1446,"total":1787,"name":"Bowman, North Dakota","coordinates":[-103.50594,46.11014]}, {"dem":472,"rep":1192,"total":1777,"name":"Granite, Montana","coordinates":[-113.42735,46.39595]}, {"dem":314,"rep":1403,"total":1770,"name":"Haskell, Texas","coordinates":[-99.73077,33.17596]}, {"dem":266,"rep":1455,"total":1762,"name":"Martin, Texas","coordinates":[-101.96183,32.30982]}, {"dem":256,"rep":1474,"total":1759,"name":"Owsley, Kentucky","coordinates":[-83.69163,37.42362]}, {"dem":151,"rep":1547,"total":1759,"name":"Roger Mills, Oklahoma","coordinates":[-99.74157,35.70855]}, {"dem":360,"rep":1184,"total":1748,"name":"Lincoln, Idaho","coordinates":[-114.15389,42.98618]}, {"dem":216,"rep":1486,"total":1745,"name":"Mercer, Missouri","coordinates":[-93.56763,40.42141]}, {"dem":720,"rep":975,"total":1739,"name":"Tyrrell, North Carolina","coordinates":[-76.16534,35.87041]}, {"dem":403,"rep":1265,"total":1729,"name":"Fisher, Texas","coordinates":[-100.40311,32.74047]}, {"dem":468,"rep":1181,"total":1728,"name":"Crosby, Texas","coordinates":[-101.2987,33.60914]}, {"dem":210,"rep":1415,"total":1720,"name":"Meade, Kansas","coordinates":[-100.36009,37.24388]}, {"dem":347,"rep":1241,"total":1719,"name":"Foster, North Dakota","coordinates":[-98.87287,47.47143]}, {"dem":536,"rep":1025,"total":1717,"name":"Nelson, North Dakota","coordinates":[-98.20442,47.91866]}, {"dem":306,"rep":1330,"total":1708,"name":"Webster, Nebraska","coordinates":[-98.49858,40.18064]}, {"dem":888,"rep":723,"total":1708,"name":"Dewey, South Dakota","coordinates":[-100.83795,45.14804]}, {"dem":320,"rep":1216,"total":1702,"name":"Union, New Mexico","coordinates":[-103.47572,36.48808]}, {"dem":181,"rep":1462,"total":1695,"name":"Hemphill, Texas","coordinates":[-100.27921,35.81595]}, {"dem":262,"rep":1382,"total":1681,"name":"Real, Texas","coordinates":[-99.81254,29.83009]}, {"dem":230,"rep":1330,"total":1677,"name":"Kimball, Nebraska","coordinates":[-103.70315,41.19927]}, {"dem":250,"rep":1347,"total":1673,"name":"Franklin, Nebraska","coordinates":[-98.96208,40.1832]}, {"dem":398,"rep":1139,"total":1657,"name":"Clark, South Dakota","coordinates":[-97.72491,44.85521]}, {"dem":281,"rep":1261,"total":1621,"name":"Nance, Nebraska","coordinates":[-97.9914,41.40238]}, {"dem":188,"rep":1333,"total":1606,"name":"Perkins, South Dakota","coordinates":[-102.46799,45.48338]}, {"dem":214,"rep":1338,"total":1605,"name":"Douglas, South Dakota","coordinates":[-98.35843,43.3915]}, {"dem":153,"rep":1385,"total":1597,"name":"Brown, Nebraska","coordinates":[-99.92391,42.35956]}, {"dem":270,"rep":1202,"total":1590,"name":"Lewis, Idaho","coordinates":[-116.42376,46.23632]}, {"dem":340,"rep":1150,"total":1573,"name":"Sherman, Nebraska","coordinates":[-98.97284,41.21874]}, {"dem":329,"rep":1148,"total":1567,"name":"Stanley, South Dakota","coordinates":[-100.74916,44.41554]}, {"dem":222,"rep":1261,"total":1544,"name":"Dallam, Texas","coordinates":[-102.59402,36.28636]}, {"dem":339,"rep":1079,"total":1527,"name":"Crowley, Colorado","coordinates":[-103.77273,38.30618]}, {"dem":249,"rep":1207,"total":1513,"name":"Hardeman, Texas","coordinates":[-99.74569,34.2899]}, {"dem":103,"rep":1378,"total":1504,"name":"Shackelford, Texas","coordinates":[-99.347,32.74381]}, {"dem":233,"rep":1197,"total":1503,"name":"Rush, Kansas","coordinates":[-99.30918,38.52359]}, {"dem":134,"rep":1318,"total":1499,"name":"Harper, Oklahoma","coordinates":[-99.6628,36.80035]}, {"dem":191,"rep":1267,"total":1499,"name":"Baylor, Texas","coordinates":[-99.20818,33.6188]}, {"dem":180,"rep":1223,"total":1494,"name":"Jewell, Kansas","coordinates":[-98.22261,39.777]}, {"dem":154,"rep":1279,"total":1484,"name":"Fallon, Montana","coordinates":[-104.40571,46.31818]}, {"dem":230,"rep":1225,"total":1484,"name":"Garza, Texas","coordinates":[-101.30113,33.18379]}, {"dem":198,"rep":1227,"total":1482,"name":"Trego, Kansas","coordinates":[-99.86542,38.9213]}, {"dem":197,"rep":1236,"total":1481,"name":"Chautauqua, Kansas","coordinates":[-96.24539,37.15425]}, {"dem":163,"rep":1220,"total":1472,"name":"Rawlins, Kansas","coordinates":[-101.07673,39.78619]}, {"dem":161,"rep":1232,"total":1468,"name":"Hitchcock, Nebraska","coordinates":[-101.04421,40.17689]}, {"dem":191,"rep":1225,"total":1465,"name":"Donley, Texas","coordinates":[-100.81584,34.95503]}, {"dem":215,"rep":1179,"total":1464,"name":"Lincoln, Kansas","coordinates":[-98.21428,39.04728]}, {"dem":383,"rep":1021,"total":1460,"name":"Norton, Virginia","coordinates":[-82.62599,36.93154]}, {"dem":161,"rep":1217,"total":1455,"name":"Perkins, Nebraska","coordinates":[-101.62746,40.85764]}, {"dem":162,"rep":1228,"total":1454,"name":"Ness, Kansas","coordinates":[-99.90874,38.48043]}, {"dem":178,"rep":1210,"total":1452,"name":"Decatur, Kansas","coordinates":[-100.4597,39.78354]}, {"dem":235,"rep":1100,"total":1446,"name":"McIntosh, North Dakota","coordinates":[-99.41648,46.10868]}, {"dem":273,"rep":1082,"total":1443,"name":"Woodson, Kansas","coordinates":[-95.75846,37.88819]}, {"dem":650,"rep":775,"total":1440,"name":"Baker, Georgia","coordinates":[-84.45488,31.31957]}, {"dem":527,"rep":814,"total":1434,"name":"Keweenaw, Michigan","coordinates":[-88.14879,47.68197]}, {"dem":458,"rep":936,"total":1430,"name":"Kinney, Texas","coordinates":[-100.4177,29.34708]}, {"dem":140,"rep":1265,"total":1423,"name":"Coke, Texas","coordinates":[-100.63523,31.87711]}, {"dem":369,"rep":977,"total":1421,"name":"Lyman, South Dakota","coordinates":[-99.84192,43.89481]}, {"dem":271,"rep":966,"total":1421,"name":"Wayne, Utah","coordinates":[-110.99087,38.25984]}, {"dem":313,"rep":1075,"total":1416,"name":"Sutton, Texas","coordinates":[-100.51335,30.52218]}, {"dem":181,"rep":1173,"total":1407,"name":"Cheyenne, Kansas","coordinates":[-101.72732,39.78991]}, {"dem":340,"rep":974,"total":1407,"name":"Aurora, South Dakota","coordinates":[-98.57758,43.72471]}, {"dem":372,"rep":980,"total":1395,"name":"Crockett, Texas","coordinates":[-101.40421,30.71753]}, {"dem":371,"rep":958,"total":1391,"name":"Highland, Virginia","coordinates":[-79.56447,38.36624]}, {"dem":594,"rep":751,"total":1390,"name":"Chattahoochee, Georgia","coordinates":[-84.78802,32.34744]}, {"dem":138,"rep":1235,"total":1390,"name":"Glascock, Georgia","coordinates":[-82.60691,33.22749]}, {"dem":299,"rep":1049,"total":1384,"name":"Crane, Texas","coordinates":[-102.48777,31.42279]}, {"dem":185,"rep":1108,"total":1381,"name":"Grant, North Dakota","coordinates":[-101.63904,46.35782]}, {"dem":179,"rep":1111,"total":1376,"name":"Kidder, North Dakota","coordinates":[-99.73119,46.93827]}, {"dem":127,"rep":1197,"total":1374,"name":"Sheridan, Kansas","coordinates":[-100.44122,39.35054]}, {"dem":316,"rep":969,"total":1369,"name":"Chase, Kansas","coordinates":[-96.59402,38.29947]}, {"dem":247,"rep":1078,"total":1367,"name":"Knox, Texas","coordinates":[-99.73035,33.61188]}, {"dem":267,"rep":1015,"total":1364,"name":"Sedgwick, Colorado","coordinates":[-102.35535,40.87156]}, {"dem":149,"rep":1132,"total":1357,"name":"Logan, Kansas","coordinates":[-101.1574,38.91327]}, {"dem":245,"rep":1040,"total":1354,"name":"Haskell, Kansas","coordinates":[-100.87995,37.55497]}, {"dem":286,"rep":1007,"total":1347,"name":"Upton, Texas","coordinates":[-102.04154,31.35381]}, {"dem":149,"rep":1140,"total":1343,"name":"Gove, Kansas","coordinates":[-100.48735,38.91723]}, {"dem":215,"rep":1071,"total":1337,"name":"Potter, South Dakota","coordinates":[-99.962,45.05271]}, {"dem":135,"rep":1159,"total":1332,"name":"Lipscomb, Texas","coordinates":[-100.27268,36.28019]}, {"dem":161,"rep":1110,"total":1328,"name":"Frontier, Nebraska","coordinates":[-100.40668,40.53094]}, {"dem":279,"rep":974,"total":1327,"name":"Pawnee, Nebraska","coordinates":[-96.24522,40.13784]}, {"dem":212,"rep":1037,"total":1319,"name":"Edwards, Kansas","coordinates":[-99.30474,37.88359]}, {"dem":174,"rep":1075,"total":1316,"name":"Kearny, Kansas","coordinates":[-101.30813,37.99446]}, {"dem":115,"rep":1116,"total":1314,"name":"Niobrara, Wyoming","coordinates":[-104.46837,43.06215]}, {"dem":168,"rep":1050,"total":1296,"name":"Hettinger, North Dakota","coordinates":[-102.45423,46.4357]}, {"dem":201,"rep":993,"total":1293,"name":"Renville, North Dakota","coordinates":[-101.65815,48.71278]}, {"dem":188,"rep":1025,"total":1284,"name":"Graham, Kansas","coordinates":[-99.87989,39.35497]}, {"dem":1003,"rep":269,"total":1279,"name":"Menominee, Wisconsin","coordinates":[-88.66925,44.9913]}, {"dem":697,"rep":566,"total":1273,"name":"Clay, Georgia","coordinates":[-84.99258,31.61983]}, {"dem":298,"rep":847,"total":1265,"name":"Griggs, North Dakota","coordinates":[-98.23228,47.45633]}, {"dem":160,"rep":1048,"total":1259,"name":"Elk, Kansas","coordinates":[-96.24464,37.45602]}, {"dem":242,"rep":944,"total":1255,"name":"Dolores, Colorado","coordinates":[-108.52411,37.71172]}, {"dem":279,"rep":851,"total":1246,"name":"Garfield, Washington","coordinates":[-117.53671,46.42947]}, {"dem":758,"rep":260,"total":1232,"name":"Sioux, North Dakota","coordinates":[-101.06128,46.11061]}, {"dem":355,"rep":791,"total":1231,"name":"Eddy, North Dakota","coordinates":[-98.90047,47.72343]}, {"dem":160,"rep":914,"total":1230,"name":"Butte, Idaho","coordinates":[-113.17763,43.6851]}, {"dem":245,"rep":867,"total":1219,"name":"Divide, North Dakota","coordinates":[-103.50932,48.81475]}, {"dem":216,"rep":909,"total":1218,"name":"Adams, North Dakota","coordinates":[-102.53319,46.09681]}, {"dem":235,"rep":872,"total":1208,"name":"Judith Basin, Montana","coordinates":[-110.30532,47.03255]}, {"dem":147,"rep":995,"total":1192,"name":"Morton, Kansas","coordinates":[-101.80951,37.18524]}, {"dem":422,"rep":695,"total":1191,"name":"Jeff Davis, Texas","coordinates":[-104.19187,30.62535]}, {"dem":156,"rep":1007,"total":1182,"name":"Echols, Georgia","coordinates":[-82.89737,30.714]}, {"dem":210,"rep":912,"total":1175,"name":"Greeley, Nebraska","coordinates":[-98.53056,41.56757]}, {"dem":535,"rep":588,"total":1175,"name":"Corson, South Dakota","coordinates":[-101.17966,45.68567]}, {"dem":305,"rep":733,"total":1157,"name":"Towner, North Dakota","coordinates":[-99.24815,48.68218]}, {"dem":128,"rep":983,"total":1156,"name":"Boyd, Nebraska","coordinates":[-98.77302,42.89444]}, {"dem":145,"rep":983,"total":1156,"name":"Collingsworth, Texas","coordinates":[-100.27213,34.96335]}, {"dem":412,"rep":666,"total":1149,"name":"Bennett, South Dakota","coordinates":[-101.67718,43.18691]}, {"dem":192,"rep":892,"total":1137,"name":"McPherson, South Dakota","coordinates":[-99.21142,45.78424]}, {"dem":241,"rep":819,"total":1123,"name":"Sanborn, South Dakota","coordinates":[-98.0917,44.01894]}, {"dem":204,"rep":858,"total":1118,"name":"Faulk, South Dakota","coordinates":[-99.15356,45.06547]}, {"dem":473,"rep":630,"total":1116,"name":"Webster, Georgia","coordinates":[-84.55382,32.04669]}, {"dem":104,"rep":797,"total":1109,"name":"Rich, Utah","coordinates":[-111.24022,41.62759]}, {"dem":132,"rep":925,"total":1102,"name":"Cheyenne, Colorado","coordinates":[-102.60179,38.83564]}, {"dem":323,"rep":722,"total":1095,"name":"Jackson, South Dakota","coordinates":[-101.62632,43.6775]}, {"dem":164,"rep":893,"total":1091,"name":"Hall, Texas","coordinates":[-100.76389,34.65562]}, {"dem":114,"rep":900,"total":1079,"name":"Kiowa, Kansas","coordinates":[-99.28653,37.56123]}, {"dem":71,"rep":963,"total":1079,"name":"Cimarron, Oklahoma","coordinates":[-102.51769,36.74839]}, {"dem":153,"rep":869,"total":1075,"name":"Garden, Nebraska","coordinates":[-102.30298,41.63336]}, {"dem":303,"rep":746,"total":1073,"name":"Edwards, Texas","coordinates":[-100.30737,29.98587]}, {"dem":148,"rep":885,"total":1068,"name":"Concho, Texas","coordinates":[-99.86364,31.31888]}, {"dem":114,"rep":888,"total":1067,"name":"Logan, North Dakota","coordinates":[-99.50458,46.46927]}, {"dem":281,"rep":706,"total":1064,"name":"Miner, South Dakota","coordinates":[-97.60812,44.02154]}, {"dem":154,"rep":862,"total":1060,"name":"McCone, Montana","coordinates":[-105.75722,47.62962]}, {"dem":208,"rep":821,"total":1059,"name":"Schleicher, Texas","coordinates":[-100.52721,30.89623]}, {"dem":127,"rep":884,"total":1053,"name":"Powder River, Montana","coordinates":[-105.55534,45.40892]}, {"dem":119,"rep":895,"total":1052,"name":"Burke, North Dakota","coordinates":[-102.52008,48.78645]}, {"dem":195,"rep":808,"total":1046,"name":"Worth, Missouri","coordinates":[-94.41919,40.48049]}, {"dem":461,"rep":575,"total":1044,"name":"Quitman, Georgia","coordinates":[-85.00479,31.86293]}, {"dem":77,"rep":936,"total":1044,"name":"Haakon, South Dakota","coordinates":[-101.59544,44.28288]}, {"dem":70,"rep":924,"total":1021,"name":"Armstrong, Texas","coordinates":[-101.35663,34.96417]}, {"dem":239,"rep":671,"total":1019,"name":"Gilliam, Oregon","coordinates":[-120.3199,45.43059]}, {"dem":124,"rep":855,"total":1017,"name":"Hodgeman, Kansas","coordinates":[-99.8984,38.08749]}, {"dem":119,"rep":830,"total":1017,"name":"Oliver, North Dakota","coordinates":[-101.33141,47.11807]}, {"dem":202,"rep":732,"total":1017,"name":"Sherman, Oregon","coordinates":[-120.67851,45.39921]}, {"dem":222,"rep":759,"total":1013,"name":"Robertson, Kentucky","coordinates":[-84.06423,38.51347]}, {"dem":166,"rep":794,"total":1010,"name":"Gosper, Nebraska","coordinates":[-99.8232,40.50909]}, {"dem":120,"rep":825,"total":1005,"name":"Clark, Kansas","coordinates":[-99.81386,37.23383]}, {"dem":361,"rep":538,"total":999,"name":"Steele, North Dakota","coordinates":[-97.71892,47.45106]}, {"dem":120,"rep":809,"total":984,"name":"Deuel, Nebraska","coordinates":[-102.3326,41.1119]}, {"dem":121,"rep":821,"total":980,"name":"Garfield, Nebraska","coordinates":[-98.95123,41.90686]}, {"dem":193,"rep":729,"total":977,"name":"Meagher, Montana","coordinates":[-110.92173,46.58569]}, {"dem":225,"rep":715,"total":977,"name":"Harmon, Oklahoma","coordinates":[-99.84419,34.74597]}, {"dem":264,"rep":648,"total":967,"name":"Jerauld, South Dakota","coordinates":[-98.62317,44.0634]}, {"dem":168,"rep":730,"total":962,"name":"Daniels, Montana","coordinates":[-105.54173,48.79442]}, {"dem":206,"rep":698,"total":961,"name":"Liberty, Montana","coordinates":[-111.03692,48.55965]}, {"dem":99,"rep":796,"total":957,"name":"Golden Valley, North Dakota","coordinates":[-103.84461,46.93892]}, {"dem":140,"rep":769,"total":956,"name":"Wichita, Kansas","coordinates":[-101.34743,38.48192]}, {"dem":89,"rep":823,"total":953,"name":"Dundy, Nebraska","coordinates":[-101.68113,40.18016]}, {"dem":78,"rep":850,"total":948,"name":"Oldham, Texas","coordinates":[-102.59762,35.40192]}, {"dem":179,"rep":702,"total":946,"name":"Wheatland, Montana","coordinates":[-109.85714,46.49704]}, {"dem":96,"rep":807,"total":935,"name":"Sherman, Texas","coordinates":[-101.89926,36.27859]}, {"dem":193,"rep":620,"total":910,"name":"De Baca, New Mexico","coordinates":[-104.36869,34.35927]}, {"dem":128,"rep":755,"total":909,"name":"Dickens, Texas","coordinates":[-100.78761,33.61536]}, {"dem":167,"rep":709,"total":904,"name":"Reagan, Texas","coordinates":[-101.51439,31.37519]}, {"dem":190,"rep":679,"total":901,"name":"Cochran, Texas","coordinates":[-102.83044,33.60844]}, {"dem":545,"rep":349,"total":897,"name":"Taliaferro, Georgia","coordinates":[-82.87527,33.55931]}, {"dem":121,"rep":705,"total":876,"name":"Hamilton, Kansas","coordinates":[-101.79368,37.99524]}, {"dem":106,"rep":718,"total":871,"name":"Lane, Kansas","coordinates":[-100.46618,38.48128]}, {"dem":324,"rep":503,"total":871,"name":"Hudspeth, Texas","coordinates":[-105.37754,31.45086]}, {"dem":102,"rep":715,"total":867,"name":"Comanche, Kansas","coordinates":[-99.25129,37.18144]}, {"dem":154,"rep":682,"total":864,"name":"Menard, Texas","coordinates":[-99.85886,30.88526]}, {"dem":171,"rep":629,"total":861,"name":"Jackson, Colorado","coordinates":[-106.32924,40.66343]}, {"dem":137,"rep":679,"total":861,"name":"Sully, South Dakota","coordinates":[-100.13139,44.72232]}, {"dem":91,"rep":728,"total":855,"name":"Kiowa, Colorado","coordinates":[-102.75684,38.38766]}, {"dem":74,"rep":723,"total":854,"name":"Eureka, Nevada","coordinates":[-116.2722,39.97778]}, {"dem":105,"rep":704,"total":831,"name":"Campbell, South Dakota","coordinates":[-100.0021,45.78557]}, {"dem":155,"rep":591,"total":818,"name":"Wheeler, Oregon","coordinates":[-120.02686,44.73641]}, {"dem":84,"rep":715,"total":808,"name":"Throckmorton, Texas","coordinates":[-99.20579,33.17069]}, {"dem":46,"rep":721,"total":798,"name":"Wallace, Kansas","coordinates":[-101.7711,38.92662]}, {"dem":70,"rep":687,"total":798,"name":"Rock, Nebraska","coordinates":[-99.42085,42.39474]}, {"dem":95,"rep":650,"total":787,"name":"Sheridan, North Dakota","coordinates":[-100.33098,47.58135]}, {"dem":70,"rep":678,"total":786,"name":"Carter, Montana","coordinates":[-104.51532,45.51682]}, {"dem":38,"rep":695,"total":770,"name":"Harding, South Dakota","coordinates":[-103.47387,45.59661]}, {"dem":353,"rep":368,"total":767,"name":"Ziebach, South Dakota","coordinates":[-101.66082,44.98976]}, {"dem":454,"rep":280,"total":767,"name":"Culberson, Texas","coordinates":[-104.52694,31.4459]}, {"dem":90,"rep":660,"total":766,"name":"Irion, Texas","coordinates":[-100.9813,31.30342]}, {"dem":81,"rep":616,"total":736,"name":"Sioux, Nebraska","coordinates":[-103.73217,42.47066]}, {"dem":91,"rep":625,"total":736,"name":"Briscoe, Texas","coordinates":[-101.20589,34.52517]}, {"dem":47,"rep":626,"total":729,"name":"Piute, Utah","coordinates":[-112.12937,38.33588]}, {"dem":34,"rep":653,"total":718,"name":"Garfield, Montana","coordinates":[-106.99599,47.26718]}, {"dem":135,"rep":555,"total":701,"name":"Stonewall, Texas","coordinates":[-100.2538,33.17957]}, {"dem":395,"rep":298,"total":699,"name":"Issaquena, Mississippi","coordinates":[-91.00353,32.75553]}, {"dem":125,"rep":543,"total":690,"name":"Hyde, South Dakota","coordinates":[-99.47273,44.53717]}, {"dem":100,"rep":556,"total":689,"name":"Prairie, Montana","coordinates":[-105.50399,46.81238]}, {"dem":238,"rep":402,"total":683,"name":"Mellette, South Dakota","coordinates":[-100.76095,43.58468]}, {"dem":237,"rep":344,"total":652,"name":"Mineral, Colorado","coordinates":[-107.00323,37.54906]}, {"dem":83,"rep":534,"total":650,"name":"Greeley, Kansas","coordinates":[-101.80596,38.4804]}, {"dem":115,"rep":492,"total":637,"name":"Stanton, Kansas","coordinates":[-101.78938,37.56593]}, {"dem":70,"rep":549,"total":633,"name":"Sterling, Texas","coordinates":[-101.05491,31.83577]}, {"dem":40,"rep":566,"total":615,"name":"Motley, Texas","coordinates":[-100.79315,34.05789]}, {"dem":92,"rep":506,"total":612,"name":"Cottle, Texas","coordinates":[-100.27644,34.0919]}, {"dem":59,"rep":495,"total":605,"name":"Billings, North Dakota","coordinates":[-103.36401,47.00704]}, {"dem":34,"rep":553,"total":604,"name":"Glasscock, Texas","coordinates":[-101.52149,31.868]}, {"dem":334,"rep":217,"total":602,"name":"Alpine, California","coordinates":[-119.79835,38.62178]}, {"dem":110,"rep":410,"total":590,"name":"Camas, Idaho","coordinates":[-114.77213,43.50255]}, {"dem":197,"rep":339,"total":589,"name":"Hinsdale, Colorado","coordinates":[-107.33826,37.82116]}, {"dem":69,"rep":450,"total":558,"name":"Jones, South Dakota","coordinates":[-100.68613,43.95199]}, {"dem":20,"rep":524,"total":554,"name":"Roberts, Texas","coordinates":[-100.83668,35.83859]}, {"dem":55,"rep":463,"total":541,"name":"Wibaux, Montana","coordinates":[-104.27451,46.96296]}, {"dem":156,"rep":311,"total":527,"name":"Harding, New Mexico","coordinates":[-103.84792,35.85851]}, {"dem":40,"rep":460,"total":519,"name":"Keya Paha, Nebraska","coordinates":[-99.71835,42.87548]}, {"dem":30,"rep":472,"total":514,"name":"Hayes, Nebraska","coordinates":[-101.04796,40.53723]}, {"dem":113,"rep":383,"total":513,"name":"Foard, Texas","coordinates":[-99.81682,33.9633]}, {"dem":265,"rep":215,"total":506,"name":"San Juan, Colorado","coordinates":[-107.67025,37.78104]}, {"dem":40,"rep":454,"total":499,"name":"McMullen, Texas","coordinates":[-98.57885,28.38492]}, {"dem":296,"rep":171,"total":490,"name":"Buffalo, South Dakota","coordinates":[-99.20399,44.0443]}, {"dem":71,"rep":365,"total":474,"name":"Golden Valley, Montana","coordinates":[-109.17458,46.38062]}, {"dem":77,"rep":331,"total":474,"name":"Daggett, Utah","coordinates":[-109.50578,40.89009]}, {"dem":62,"rep":377,"total":465,"name":"Wheeler, Nebraska","coordinates":[-98.52085,41.92257]}, {"dem":32,"rep":400,"total":453,"name":"Logan, Nebraska","coordinates":[-100.44366,41.54215]}, {"dem":59,"rep":351,"total":443,"name":"Treasure, Montana","coordinates":[-107.28577,46.22944]}, {"dem":140,"rep":288,"total":438,"name":"Terrell, Texas","coordinates":[-102.07251,30.23234]}, {"dem":59,"rep":360,"total":434,"name":"Kent, Texas","coordinates":[-100.76971,33.18477]}, {"dem":43,"rep":362,"total":430,"name":"Slope, North Dakota","coordinates":[-103.46246,46.44583]}, {"dem":65,"rep":329,"total":423,"name":"Esmeralda, Nevada","coordinates":[-117.63238,37.77896]}, {"dem":40,"rep":355,"total":417,"name":"Hooker, Nebraska","coordinates":[-101.11732,41.92031]}, {"dem":20,"rep":367,"total":405,"name":"Grant, Nebraska","coordinates":[-101.75596,41.91395]}, {"dem":19,"rep":357,"total":402,"name":"Banner, Nebraska","coordinates":[-103.72626,41.53974]}, {"dem":30,"rep":344,"total":393,"name":"Thomas, Nebraska","coordinates":[-100.5247,41.85572]}, {"dem":48,"rep":323,"total":385,"name":"Loup, Nebraska","coordinates":[-99.50985,41.90318]}, {"dem":31,"rep":330,"total":365,"name":"Borden, Texas","coordinates":[-101.43919,32.73858]}, {"dem":30,"rep":278,"total":322,"name":"Petroleum, Montana","coordinates":[-108.22657,47.14191]}, {"dem":30,"rep":276,"total":317,"name":"Blaine, Nebraska","coordinates":[-99.9964,41.93194]}, {"dem":14,"rep":257,"total":287,"name":"McPherson, Nebraska","coordinates":[-101.12085,41.64841]}, {"dem":44,"rep":203,"total":283,"name":"Clark, Idaho","coordinates":[-112.35461,44.29021]}, {"dem":17,"rep":244,"total":273,"name":"Arthur, Nebraska","coordinates":[-101.69591,41.57192]}, {"dem":99,"rep":84,"total":186,"name":"Kenedy, Texas","coordinates":[-97.59114,26.89021]}, {"dem":5,"rep":149,"total":159,"name":"King, Texas","coordinates":[-100.24534,33.61426]}, {"dem":4,"rep":58,"total":65,"name":"Loving, Texas","coordinates":[-103.56122,31.84493]}] ================================================ FILE: examples/.data/us-income.geojson ================================================ { "type": "FeatureCollection", "features": [ {"type":"Feature","properties":{"name":"Maine","income":{"1995":31189,"1996":33002,"1997":33140,"1998":35560,"1999":36902,"2000":37589,"2001":38036,"2002":37963,"2003":39212,"2004":41287,"2005":42648,"2006":43472,"2007":45832,"2008":46419,"2009":45708,"2010":45882,"2011":46160,"2012":46856,"2013":47095,"2014":49381,"2015":51419}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-68.92401,43.885407],[-68.874784,43.904715],[-68.849009,43.849841],[-68.888483,43.803781],[-68.944433,43.835326],[-68.92401,43.885407]]],[[[-71.083924,45.305451],[-71.03821,45.311922],[-71.012757,45.34476],[-70.949365,45.331536],[-70.912111,45.296197],[-70.892822,45.239172],[-70.84443,45.234513],[-70.83401953744008,45.27179440239679],[-70.82979,45.286941],[-70.808613,45.311606],[-70.819471,45.341435],[-70.806244,45.376558],[-70.825612,45.400305],[-70.781471,45.431159],[-70.755567,45.428361],[-70.729972,45.399359],[-70.677995,45.394362],[-70.634661,45.383608],[-70.635498,45.427817],[-70.674903,45.452399],[-70.723396,45.510394],[-70.688214,45.563981],[-70.649578,45.598147],[-70.591275,45.630551],[-70.5528239033785,45.66780605788509],[-70.552793,45.667836],[-70.446903,45.704044],[-70.383552,45.734869],[-70.415684,45.786158],[-70.39662,45.808486],[-70.329748,45.853795],[-70.259117,45.890755],[-70.252526,45.933176],[-70.26541,45.962692],[-70.31297,45.961856],[-70.303034,45.998976],[-70.317629,46.01908],[-70.306734,46.061344],[-70.266349,46.100993],[-70.239566,46.142762],[-70.290896,46.185838],[-70.255492,46.246444],[-70.232682,46.284428],[-70.205719,46.299865],[-70.207415,46.331316],[-70.161337,46.360984],[-70.118597,46.384233],[-70.080292,46.410531],[-70.053748,46.429236],[-70.02301978705616,46.57348647251729],[-69.997086,46.69523],[-69.818552,46.87503],[-69.566383,47.125032],[-69.439198,47.250033],[-69.219996,47.457159],[-69.156074,47.451035],[-69.108215,47.435831],[-69.039301,47.42217],[-69.053885,47.377878],[-69.0402,47.2451],[-68.966433,47.212712],[-68.900985,47.178519],[-68.803537,47.216033],[-68.675913,47.242626],[-68.604819,47.249418],[-68.588725,47.281721],[-68.507432,47.296636],[-68.460064,47.286065],[-68.375615,47.292268],[-68.384281,47.326943],[-68.361559,47.355605],[-68.26971,47.353733],[-68.204263,47.33973],[-68.153509,47.314038],[-68.082896,47.271921],[-67.998171,47.217842],[-67.952269,47.196142],[-67.889155,47.118772],[-67.789761,47.065744],[-67.789799,46.794868],[-67.788406,46.601795],[-67.782114,46.279381],[-67.780438,46.038452],[-67.779984,45.938163],[-67.750422,45.917898],[-67.803678,45.869379],[-67.763955,45.829983],[-67.803626,45.781624],[-67.781892,45.731189],[-67.80289429507708,45.67892788546318],[-67.803313,45.677886],[-67.710464,45.679372],[-67.675417,45.630959],[-67.631762,45.621409],[-67.534919,45.595428],[-67.455406,45.604665],[-67.423646,45.572153],[-67.417417,45.501985],[-67.476855,45.49724],[-67.484328,45.451955],[-67.427243,45.37369],[-67.460554,45.300379],[-67.480256,45.268185],[-67.453473,45.241127],[-67.390579,45.154114],[-67.339869,45.125594],[-67.298209,45.146672],[-67.271076,45.191081],[-67.203933,45.171407],[-67.161247,45.162879],[-67.112414,45.112323],[-67.090786,45.068721],[-67.082074,45.029608],[-67.033474,44.939923],[-66.983558,44.903277],[-66.99296,44.849181],[-66.949895,44.817419],[-67.02615,44.768199],[-67.073439,44.741957],[-67.116745,44.706106],[-67.169857,44.662105],[-67.234275,44.637201],[-67.293403,44.599265],[-67.368269,44.624672],[-67.398987,44.602631],[-67.448513,44.600322],[-67.491751,44.556123],[-67.521168,44.50991],[-67.503208,44.476918],[-67.579726,44.429131],[-67.634806,44.487054],[-67.653123,44.525823],[-67.70668,44.501975],[-67.793589,44.494779],[-67.837938,44.46467],[-67.855108,44.419434],[-67.899571,44.394078],[-67.936531,44.411187],[-67.94384395705518,44.407015790843],[-67.978876,44.387034],[-68.01399,44.390255],[-68.049334,44.33073],[-68.103757,44.364362],[-68.125624,44.387127],[-68.189155,44.373833],[-68.173608,44.328397],[-68.191924,44.306675],[-68.22949,44.266918],[-68.17433,44.225908],[-68.306519,44.234829],[-68.314789,44.197157],[-68.331032,44.10758],[-68.438518,44.11618],[-68.502942,44.099722],[-68.53141420235178,44.08985238025649],[-68.584101,44.071589],[-68.617085,44.010097],[-68.657031,44.003823],[-68.669383,44.076359],[-68.77965,44.057754],[-68.874139,44.025359],[-68.905098,44.077344],[-68.935327,44.13038],[-68.888597,44.15955],[-68.93497643176178,44.20290747393729],[-68.95189,44.218719],[-69.02107454500458,44.23043531412289],[-69.040193,44.233673],[-69.054546,44.171542],[-69.075667,44.129991],[-69.031878,44.079036],[-69.068112,44.039768],[-69.043912,44.006336],[-69.077028,43.973654],[-69.131536,43.976089],[-69.17498,43.976949],[-69.212939,43.921404],[-69.242812,43.918818],[-69.279918,43.879579],[-69.321031,43.856708],[-69.354577,43.917765],[-69.38048971934309,43.943640233556486],[-69.393288,43.95642],[-69.422048,43.923047],[-69.438066,43.909539],[-69.50329,43.837673],[-69.552606,43.841347],[-69.578527,43.823316],[-69.650818,43.803785],[-69.69581545625987,43.79605496729129],[-69.717074,43.792403],[-69.754091,43.743866],[-69.807359,43.728081],[-69.833471,43.701281],[-69.855081,43.704746],[-69.862155,43.758962],[-69.88740612415768,43.766593379451784],[-69.915593,43.775112],[-69.983685,43.744395],[-70.001273,43.710388],[-70.06277666023647,43.71335994651279],[-70.071304,43.713772],[-70.096039,43.672276],[-70.168227,43.675136],[-70.190704,43.645582],[-70.217087,43.596717],[-70.206123,43.557627],[-70.245499,43.539635],[-70.321116,43.527262],[-70.33873747724839,43.52810927936889],[-70.361214,43.52919],[-70.385615,43.487031],[-70.327303,43.458521],[-70.383981,43.41294],[-70.416311,43.361059],[-70.465975,43.340246],[-70.517695,43.344037],[-70.53414906595059,43.33395724074578],[-70.553854,43.321886],[-70.585184,43.270113],[-70.57698663416599,43.228019173145185],[-70.575787,43.221859],[-70.596185,43.163466],[-70.62251,43.134573],[-70.665958,43.076234],[-70.703818,43.059825],[-70.756397,43.079988],[-70.819549285713,43.123230973431184],[-70.8281,43.129086],[-70.824801,43.179685],[-70.82477671206809,43.1797631051822],[-70.813119,43.217252],[-70.872585,43.270152],[-70.923949,43.324768],[-70.984335,43.376128],[-70.968359,43.429283],[-70.96078889604699,43.47408873362158],[-70.954755,43.509802],[-70.96379267980639,43.54022095536649],[-70.972716,43.570255],[-70.981946,43.70096],[-70.98725804674599,43.79297359288418],[-70.989929,43.839239],[-71.001367,44.092931],[-71.008736,44.258825],[-71.01027116786828,44.284888321572],[-71.01127,44.301846],[-71.01357590381458,44.34083745255949],[-71.01946172948549,44.44036323978749],[-71.022992,44.500058],[-71.036705,44.736498],[-71.057861,45.000049],[-71.083924,45.305451]]]]}}, {"type":"Feature","properties":{"name":"Hawaii","income":{"1995":43973,"1996":43677,"1997":43627,"1998":41627,"1999":44755,"2000":49005,"2001":46535,"2002":47424,"2003":48274,"2004":51359,"2005":56133,"2006":60554,"2007":62613,"2008":66701,"2009":63741,"2010":62774,"2011":62071,"2012":66086,"2013":67798,"2014":69549,"2015":73097}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-156.049651,19.780452],[-156.006267,19.81758],[-155.976651,19.85053],[-155.949251,19.857034],[-155.915662,19.887126],[-155.892533,19.932162],[-155.856588,19.968885],[-155.831948,19.982775],[-155.825473,20.025944],[-155.850385,20.062506],[-155.890646,20.123576],[-155.90278,20.177073],[-155.890663,20.25524],[-155.853293,20.271548],[-155.798884,20.254115],[-155.737004,20.222773],[-155.704331,20.191695],[-155.637459,20.153051],[-155.598033,20.124539],[-155.558933,20.13157],[-155.502561,20.114155],[-155.387578,20.067119],[-155.270316,20.014525],[-155.166625,19.93789],[-155.124618,19.897288],[-155.086341,19.855399],[-155.091216,19.776368],[-155.087118,19.728013],[-155.045382,19.739824],[-155.006423,19.739286],[-154.981102,19.690687],[-154.974342,19.633201],[-154.947106,19.604856],[-154.852618,19.549172],[-154.814417,19.53009],[-154.816009,19.500648],[-154.876618,19.433223],[-154.944185,19.381852],[-155.020537,19.331317],[-155.113272,19.290613],[-155.159635,19.268375],[-155.205892,19.260907],[-155.264619,19.274213],[-155.31337,19.250698],[-155.360631,19.20893],[-155.390701,19.201171],[-155.453516,19.151952],[-155.505281,19.137908],[-155.555326,19.069377],[-155.590697,19.007673],[-155.613966,18.970399],[-155.638054,18.941723],[-155.672005,18.917466],[-155.726043,18.969437],[-155.806109,19.013967],[-155.88155,19.036644],[-155.914216,19.099147],[-155.912069,19.179114],[-155.902565,19.258427],[-155.890842,19.298905],[-155.888701,19.348031],[-155.909087,19.415455],[-155.924732,19.45391],[-155.95149,19.486649],[-155.96935,19.555963],[-155.978206,19.608159],[-155.997728,19.642816],[-156.028982,19.650098],[-156.033326,19.66923],[-156.064364,19.730766],[-156.049651,19.780452]]],[[[-156.69989,20.920629],[-156.680905,20.980262],[-156.619581,21.027793],[-156.562773,21.016167],[-156.518707,20.954662],[-156.481055,20.898199],[-156.403304,20.915826],[-156.332817,20.94645],[-156.242555,20.937838],[-156.19471,20.891975],[-156.132669,20.861369],[-156.059788,20.81054],[-156.003532,20.795545],[-155.985413,20.744245],[-156.00187,20.698064],[-156.043786,20.664902],[-156.129898,20.627523],[-156.210258,20.628518],[-156.284391,20.596488],[-156.377633,20.578427],[-156.431872,20.598143],[-156.443673,20.656018],[-156.458438,20.736676],[-156.462242,20.753952],[-156.473562,20.790756],[-156.506026,20.799463],[-156.537752,20.778408],[-156.554617,20.786096],[-156.631794,20.82124],[-156.687804,20.89072],[-156.69989,20.920629]]],[[[-156.670469,20.559909],[-156.610734,20.59377],[-156.56714,20.604895],[-156.543034,20.580115],[-156.539643,20.527644],[-156.586238,20.511711],[-156.668809,20.504738],[-156.702265,20.532451],[-156.670469,20.559909]]],[[[-157.05913,20.913407],[-157.010001,20.929757],[-156.937529,20.925274],[-156.873125,20.894679],[-156.837047,20.863575],[-156.808469,20.820396],[-156.838321,20.764575],[-156.890295,20.744855],[-156.909081,20.739533],[-156.96789,20.73508],[-156.990678,20.775902],[-156.991834,20.826603],[-157.010911,20.854476],[-157.059663,20.884634],[-157.05913,20.913407]]],[[[-157.27722,21.158431],[-157.249695,21.184401],[-157.26069,21.225684],[-157.202125,21.219298],[-157.128207,21.201488],[-157.039987,21.190909],[-157.01426786929898,21.200694266258296],[-156.984032,21.212198],[-156.962847,21.212131],[-156.921108,21.169068],[-156.91785956119898,21.1690213462811],[-156.841592,21.167926],[-156.742231,21.176214],[-156.709106,21.158655],[-156.739342,21.111336],[-156.8022,21.067095],[-156.877137,21.0493],[-156.953872,21.066128],[-157.02617,21.089015],[-157.08066,21.101976],[-157.171606,21.090701],[-157.252534,21.08767],[-157.310748,21.101627],[-157.27722,21.158431]]],[[[-158.232192,21.583806],[-158.12561,21.586739],[-158.079895,21.628101],[-158.050692,21.671215],[-157.9923,21.708],[-157.968628,21.712704],[-157.924591,21.651183],[-157.87735,21.575277],[-157.836945,21.529945],[-157.84549,21.466747],[-157.8139,21.4403],[-157.764572,21.461335],[-157.722506,21.459225],[-157.724324,21.403311],[-157.7106,21.3585],[-157.6518,21.3139],[-157.65510785904,21.309280288451294],[-157.673069,21.284196],[-157.7001,21.264],[-157.7572,21.278],[-157.779944,21.265252],[-157.8096,21.2577],[-157.851048,21.28453],[-157.89,21.3065],[-157.950736,21.312509],[-157.981525,21.315898],[-158.0245,21.3093],[-158.0883,21.2988],[-158.1033,21.2979],[-158.129371,21.344818],[-158.13093136645998,21.34895584799669],[-158.1403,21.3738],[-158.1792,21.4043],[-158.182648,21.430073],[-158.233,21.4876],[-158.231171,21.523857],[-158.277679,21.578789],[-158.232192,21.583806]]],[[[-159.783746,22.064897],[-159.745247,22.097508],[-159.730544,22.139953],[-159.705531,22.159321],[-159.61165,22.201388],[-159.581058,22.223488],[-159.543924,22.221695],[-159.510756,22.203548],[-159.487939,22.229512],[-159.431707,22.220015],[-159.402466,22.232603],[-159.361507,22.214092],[-159.312293,22.183082],[-159.293013,22.12296],[-159.31828,22.061417],[-159.334489,22.041698],[-159.332564,21.999352],[-159.33768,21.951173],[-159.385271,21.912439],[-159.444868,21.868627],[-159.526918,21.883886],[-159.574521,21.892806],[-159.603279,21.892248],[-159.649766,21.933848],[-159.707795,21.961229],[-159.754795,21.977772],[-159.786702,22.018801],[-159.783746,22.064897]]],[[[-160.24961,21.815145],[-160.228965,21.889117],[-160.193959,21.922386],[-160.13705,21.948632],[-160.122262,21.962881],[-160.112746,21.995245],[-160.072123,22.003334],[-160.058543,21.99638],[-160.051128,21.98106],[-160.070292,21.963951],[-160.085787,21.927295],[-160.079065,21.89608],[-160.124283,21.876789],[-160.156092,21.86793],[-160.174796,21.846923],[-160.189782,21.82245],[-160.205851,21.779518],[-160.230373,21.789675],[-160.24961,21.815145]]]]}}, {"type":"Feature","properties":{"name":"Arizona","income":{"1995":31736,"1996":32708,"1997":34751,"1998":37281,"1999":38642,"2000":40437,"2001":41403,"2002":40724,"2003":41963,"2004":43696,"2005":44402,"2006":47315,"2007":49923,"2008":51009,"2009":48711,"2010":46787,"2011":46710,"2012":47796,"2013":48504,"2014":50036,"2015":51473}},"geometry":{"type":"Polygon","coordinates":[[[-114.799683,32.593621],[-114.809393,32.617119],[-114.76495,32.649391],[-114.719633,32.718763],[-114.705717,32.741581],[-114.667493,32.734226],[-114.61738652396197,32.74105277317659],[-114.570675,32.747417],[-114.531746,32.782503],[-114.468971,32.845155],[-114.463127,32.901884],[-114.47664,32.923628],[-114.481315,32.972064],[-114.511343,33.023455],[-114.51706679028098,33.024628763568494],[-114.575161,33.036542],[-114.628293,33.031052],[-114.670803,33.037984],[-114.706175,33.105335],[-114.679359,33.159519],[-114.678097,33.2303],[-114.674491,33.255597],[-114.723259,33.288079],[-114.707962,33.323421],[-114.707348,33.376628],[-114.725282,33.405048],[-114.673901,33.418299],[-114.635183,33.422726],[-114.62914651818897,33.43354499999979],[-114.597283,33.490653],[-114.524599,33.552231],[-114.529186,33.60665],[-114.525201,33.661583],[-114.504993,33.693022],[-114.496565,33.719155],[-114.504863,33.760465],[-114.520465,33.827778],[-114.505638,33.864276],[-114.508708,33.90064],[-114.534987,33.928499],[-114.509568,33.957264],[-114.454807,34.010968],[-114.435504,34.042615],[-114.43009113851998,34.07893140627949],[-114.428026,34.092787],[-114.405941,34.11154],[-114.348052,34.134458],[-114.292806,34.166725],[-114.229715,34.186928],[-114.17805,34.239969],[-114.139055,34.259538],[-114.14081715127998,34.30312751388169],[-114.14093,34.305919],[-114.172845,34.344979],[-114.264317,34.401329],[-114.335372,34.450038],[-114.378852,34.450376],[-114.378223,34.516521],[-114.422382,34.580711],[-114.465246,34.691202],[-114.490971,34.724848],[-114.576452,34.8153],[-114.634382,34.87289],[-114.629769,34.94304],[-114.633487,35.001857],[-114.625069,35.068478],[-114.619905,35.121632],[-114.59912,35.12105],[-114.572747,35.138725],[-114.587129,35.262376],[-114.627137,35.409504],[-114.6645,35.449497],[-114.663105,35.524491],[-114.653406,35.610789],[-114.689407,35.651412],[-114.697309,35.733686],[-114.70371,35.814585],[-114.669687,35.865084],[-114.700271,35.901772],[-114.731159,35.943916],[-114.742779,36.009963],[-114.74329924588599,36.06593517376009],[-114.743342,36.070535],[-114.736165,36.104367],[-114.666538,36.117343],[-114.627855,36.141012],[-114.572031,36.15161],[-114.511721,36.150956],[-114.487034,36.129396],[-114.448654,36.12641],[-114.41695,36.145761],[-114.372106,36.143114],[-114.337273,36.10802],[-114.316109,36.063109],[-114.270645,36.03572],[-114.21369,36.015613],[-114.151725,36.024563],[-114.138203,36.053161],[-114.09987,36.121654],[-114.046838,36.194069],[-114.048226,36.268874],[-114.047584,36.325573],[-114.049493,36.604059],[-114.05016077608799,36.84314153968939],[-114.0506,37.000396],[-113.965907,37.000025],[-112.966471,37.000219],[-112.89919089761598,37.000301228628395],[-112.82950194437198,37.000386401314394],[-112.545094,37.000734],[-112.538571,37.000744128882],[-112.35769,37.001025],[-111.41278398787297,37.001477687156],[-111.405869,37.001481],[-111.278286,37.000465],[-111.066496,37.002389],[-110.75069,37.003197],[-110.75068647892799,37.00319693472519],[-110.47019,36.997997],[-110.00068181858897,36.99796800029759],[-110.000677,36.997968],[-109.495338,36.999105],[-109.045223,36.999084],[-109.045433,36.874589],[-109.045729,36.117028],[-109.04587116820498,36.002701630519],[-109.046024,35.8798],[-109.046296,35.614251],[-109.046796,35.363606],[-109.04635589438398,35.17550718835119],[-109.04585123518297,34.959818515836695],[-109.045851,34.959718],[-109.04613893536299,34.57929101281789],[-109.046182,34.522393],[-109.046426,33.875052],[-109.04660747392198,33.77822380035048],[-109.047298,33.409783],[-109.047237,33.208965],[-109.04723698053698,33.20889503155078],[-109.04711706230997,32.777794000947694],[-109.047117,32.77757],[-109.047612,32.426377],[-109.04761200321998,32.426375388514195],[-109.048296,32.084093],[-109.049195,31.796551],[-109.050044,31.332502],[-109.829689,31.334067],[-110.46017261044499,31.333141378991595],[-111.074825,31.332239],[-111.36696937116398,31.424824287191587],[-112.365043,31.74113],[-113.33376797301499,32.04024908009009],[-113.750756,32.169005],[-114.813613,32.494277],[-114.811536,32.522834],[-114.795635,32.550956],[-114.814185,32.564788],[-114.799683,32.593621]]]}}, {"type":"Feature","properties":{"name":"Arkansas","income":{"1995":26515,"1996":27367,"1997":27875,"1998":29212,"1999":31217,"2000":31496,"2001":32864,"2002":32819,"2003":33445,"2004":35295,"2005":35041,"2006":36627,"2007":38239,"2008":38820,"2009":37888,"2010":38413,"2011":38889,"2012":40151,"2013":40605,"2014":41335,"2015":42046}},"geometry":{"type":"Polygon","coordinates":[[[-94.617919,36.499414],[-94.361203,36.4996],[-94.07708826689347,36.49897595722189],[-93.95919,36.498717],[-93.86675821167105,36.49886616468489],[-93.700171,36.499135],[-93.58428154735566,36.498901678628286],[-93.426989,36.498585],[-93.31532710652907,36.49831272629789],[-93.29344735563399,36.49825937523429],[-93.125969,36.497851],[-92.85404911498487,36.498023381141586],[-92.838876,36.498033],[-92.77233389337206,36.498083154079396],[-92.564238,36.49824],[-92.52913658104367,36.498165682985295],[-92.350277,36.497787],[-92.15030624950118,36.498140333324194],[-92.12042910438808,36.49819312399969],[-91.985802,36.498431],[-91.67234245644367,36.499256633798886],[-91.64259,36.499335],[-91.45000491813738,36.49754021318469],[-91.40713744351747,36.497140711948596],[-91.404915,36.49712],[-91.12653887456469,36.497797701019394],[-91.017974,36.498062],[-90.78424415513118,36.49846220012908],[-90.765672,36.498494],[-90.57617906556729,36.498405927798],[-90.494575,36.498368],[-90.22074905391537,36.495937592194494],[-90.153871,36.495344],[-90.141399,36.459874],[-90.131038,36.415069],[-90.066136,36.386272],[-90.063526,36.356911],[-90.06398,36.303038],[-90.114922,36.265595],[-90.155928,36.214074],[-90.18912798221689,36.19898660866739],[-90.220425,36.184764],[-90.235585,36.139474],[-90.294492,36.112949],[-90.339343,36.047112],[-90.368718,35.995812],[-90.28894791527279,35.99651400421139],[-90.103842,35.998143],[-89.95937529517369,35.99901411015688],[-89.901183,35.999365],[-89.733095,36.000608],[-89.686924,35.947716],[-89.652279,35.921462],[-89.64890497034517,35.90358348231259],[-89.64727,35.89492],[-89.722634,35.873718],[-89.729517,35.847632],[-89.723426,35.809382],[-89.797053,35.782648],[-89.863874,35.747592],[-89.915491,35.754917],[-89.956589,35.695486],[-89.898916,35.650904],[-89.876548,35.626653],[-89.9325,35.607865],[-89.944754,35.560308],[-89.958498,35.541703],[-90.037615,35.550329],[-90.045805,35.496533],[-90.022064,35.457375],[-90.045306,35.415435],[-90.070549,35.423291],[-90.112504,35.410153],[-90.087903,35.36327],[-90.121864,35.304535],[-90.166594,35.274588],[-90.097947,35.249983],[-90.093285,35.203282],[-90.099777,35.164474],[-90.09061,35.118287],[-90.160058,35.12883],[-90.181387,35.091401],[-90.197146,35.050731],[-90.265296,35.040293],[-90.300697,35.028793],[-90.309297,34.995694],[-90.244476,34.937596],[-90.250095,34.90732],[-90.31142425034518,34.87285114409999],[-90.313476,34.871698],[-90.401633,34.835305],[-90.40798275379427,34.83526597928069],[-90.463795,34.834923],[-90.473527,34.788835],[-90.505494,34.764568],[-90.546053,34.702076],[-90.550158,34.663445],[-90.57328841261827,34.63367050646799],[-90.587224,34.615732],[-90.549244,34.568101],[-90.569347,34.524867],[-90.583717,34.458829],[-90.575336,34.415152],[-90.641398,34.383869],[-90.660404,34.33576],[-90.729131,34.364206],[-90.765174,34.342818],[-90.752681,34.289266],[-90.812829,34.279438],[-90.839981,34.236114],[-90.89456,34.22438],[-90.882701,34.184364],[-90.894385,34.160953],[-90.938064,34.148754],[-90.94408076019378,34.12006529477739],[-90.94479552430947,34.11665720531419],[-90.946323,34.109374],[-90.90113,34.094667],[-90.874541,34.072041],[-90.89242,34.02686],[-90.942662,34.01805],[-90.979945,34.000106],[-91.004981,33.977011],[-91.048367,33.985078],[-91.088696,33.961334],[-91.035961,33.943758],[-91.026382,33.90798],[-91.061247,33.877505],[-91.052819,33.824181],[-91.025173,33.805953],[-91.026782,33.763642],[-91.08551,33.77641],[-91.111494,33.774568],[-91.143287,33.747141],[-91.075389,33.714403],[-91.10098,33.660551],[-91.178311,33.651109],[-91.130902,33.610919],[-91.188942,33.576225],[-91.20564498594787,33.54697837093289],[-91.215671,33.529423],[-91.189375,33.493005],[-91.171799,33.462342],[-91.147663,33.427172],[-91.113764,33.393124],[-91.142219,33.348989],[-91.125539,33.280255],[-91.086137,33.273652],[-91.068708,33.232936],[-91.084366,33.180856],[-91.104317,33.131598],[-91.153015,33.135093],[-91.180836,33.098364],[-91.120379,33.05453],[-91.15960609801297,33.01124232130679],[-91.166073,33.004106],[-91.26456405022049,33.00473882427039],[-91.43593108033177,33.0058398909721],[-91.4603917718319,33.00599705570149],[-91.489176,33.006182],[-91.875128,33.007728],[-92.06910375856128,33.008482263699584],[-92.06914659248126,33.00848243025689],[-92.222825,33.00908],[-92.501383,33.01216],[-92.723553,33.014328],[-92.72474317317926,33.01434176767479],[-92.971137,33.017192],[-92.988707610715,33.01725094015219],[-93.197402,33.017951],[-93.23860696239936,33.01801587995659],[-93.377134,33.018234],[-93.49051240012037,33.01863459566629],[-93.52099355377158,33.018742293588],[-93.723273,33.019457],[-93.80490777463038,33.01939622545089],[-93.81455301343377,33.01938904487079],[-94.042964,33.019219],[-94.042719,33.160291],[-94.04294584717597,33.27124208413979],[-94.043067,33.330498],[-94.042988,33.435824],[-94.043428,33.551425],[-94.04383374780107,33.551713735585594],[-94.07267,33.572234],[-94.143024,33.577725],[-94.183395,33.592212],[-94.213605,33.570622],[-94.238868,33.576722],[-94.303742,33.564486],[-94.338422,33.567082],[-94.354165,33.556452],[-94.388052,33.565511],[-94.419057,33.577217],[-94.485875,33.637867],[-94.481842,33.789008],[-94.47726674152977,33.94091092793479],[-94.474895,34.019655],[-94.47015267816208,34.189864292126096],[-94.465425,34.359548],[-94.46116868615587,34.50745665157249],[-94.4575,34.634945],[-94.45439503413786,34.72895867317939],[-94.449058,34.890556],[-94.44750953578428,34.93397621215719],[-94.44292586168999,35.06250620957269],[-94.435316,35.275893],[-94.431515,35.369591],[-94.43391344383237,35.38636176989869],[-94.43488928759668,35.39318521558748],[-94.449696,35.496719],[-94.47311939064667,35.63854715252939],[-94.49304007242698,35.759166474327294],[-94.494549,35.768303],[-94.532071,35.987852],[-94.55190628260627,36.10222560566859],[-94.56226800249247,36.16197304097529],[-94.5862,36.299969],[-94.617919,36.499414]]]}}, {"type":"Feature","properties":{"name":"Delaware","income":{"1995":37345,"1996":39701,"1997":41315,"1998":42662,"1999":45201,"2000":47812,"2001":47876,"2002":48096,"2003":48770,"2004":49545,"2005":52508,"2006":53714,"2007":55988,"2008":58380,"2009":56985,"2010":56172,"2011":58159,"2012":58326,"2013":58244,"2014":59853,"2015":61327}},"geometry":{"type":"Polygon","coordinates":[[[-75.773786,39.7222],[-75.753228,39.757989],[-75.717059,39.792325],[-75.662846,39.821425],[-75.59431690522008,39.834594973091285],[-75.570433,39.839185],[-75.481207,39.829191],[-75.415062,39.801919],[-75.459439,39.765813],[-75.47764,39.715013],[-75.509742,39.686113],[-75.535144,39.647212],[-75.559446,39.629812],[-75.543965,39.596],[-75.512732,39.578],[-75.527676,39.535278],[-75.528088,39.498114],[-75.593068,39.479186],[-75.57183,39.438897],[-75.521682,39.387871],[-75.50564316735286,39.37039456007959],[-75.469324,39.33082],[-75.408376,39.264698],[-75.39479,39.188354],[-75.407473,39.133706],[-75.396277,39.057884],[-75.34089,39.01996],[-75.30665210950967,38.94766016332839],[-75.302552,38.939002],[-75.304078,38.91316],[-75.232029,38.844254],[-75.159022,38.790193],[-75.113331,38.782998],[-75.089473,38.797198],[-75.071805,38.696497],[-75.053973,38.536273],[-75.048939,38.451263],[-75.185455,38.451012],[-75.34128732034819,38.45243652595549],[-75.479283,38.453698],[-75.693721,38.460128],[-75.700382,38.542743],[-75.70177751524498,38.560766929078596],[-75.707551,38.635335],[-75.70755502642899,38.635385355059896],[-75.72310269333266,38.82982655652769],[-75.74815481425408,39.14313173095969],[-75.75643521556849,39.2466875371253],[-75.76044141645049,39.29678962110009],[-75.766895,39.377499],[-75.76690460670918,39.37765159355119],[-75.788596,39.722199],[-75.773786,39.7222]]]}}, {"type":"Feature","properties":{"name":"Georgia","income":{"1995":33623,"1996":33763,"1997":36372,"1998":37826,"1999":39910,"2000":42057,"2001":42006,"2002":42359,"2003":42421,"2004":42679,"2005":45564,"2006":46808,"2007":49080,"2008":50834,"2009":47469,"2010":46252,"2011":45886,"2012":47125,"2013":47765,"2014":49240,"2015":51225}},"geometry":{"type":"Polygon","coordinates":[[[-85.605165,34.984678],[-85.47433884313428,34.98367332679109],[-85.384967,34.982987],[-85.36391902893108,34.983376563140496],[-85.277556,34.984975],[-85.26505502171578,34.985077644741686],[-85.045183,34.986883],[-84.97985402523149,34.98720561397559],[-84.97697380659228,34.987219837354885],[-84.861314,34.987791],[-84.81047746688638,34.98787795522919],[-84.77583767129727,34.98793720614929],[-84.727434,34.98802],[-84.621483,34.988329],[-84.509052,34.988033],[-84.321869,34.988408],[-84.12944696263588,34.98794695395529],[-84.00533673343827,34.98764958401229],[-83.936646,34.987485],[-83.93642734425198,34.98748438337969],[-83.619985,34.986592],[-83.54918075350466,34.988803195913995],[-83.48287320429068,34.990873961286795],[-83.322768,34.995874],[-83.10861299650726,35.00065884367769],[-83.108606,35.000659],[-83.124378,34.95524],[-83.140621,34.924915],[-83.201183,34.884653],[-83.252582,34.853483],[-83.284812,34.823043],[-83.323866,34.789712],[-83.320062,34.759616],[-83.353238,34.728648],[-83.34960851091326,34.71701058262729],[-83.34003910678457,34.686327710412094],[-83.33869,34.682002],[-83.27796,34.644853],[-83.221402,34.609947],[-83.154577,34.588198],[-83.10287382603569,34.53743090976538],[-83.096858,34.531524],[-83.05057296410239,34.49505365216909],[-83.048289,34.493254],[-82.99509,34.472483],[-82.99138815318229,34.47298062723579],[-82.925766,34.481802],[-82.873831,34.471508],[-82.841997,34.399766],[-82.82342,34.358872],[-82.780308,34.296701],[-82.77462873101207,34.28836681825469],[-82.744982,34.244861],[-82.73510798894158,34.21261481224289],[-82.715373,34.148165],[-82.642797,34.081312],[-82.59502579260727,34.013517809209596],[-82.591855,34.009018],[-82.56299679858088,33.95655491052689],[-82.556835,33.945353],[-82.51295,33.936969],[-82.43115,33.867051],[-82.32448,33.820033],[-82.239098,33.730872],[-82.21593836474749,33.68775497531869],[-82.199747,33.657611],[-82.161908,33.610643],[-82.14245647450088,33.60539959999209],[-82.11465383858477,33.59790505457],[-82.10624,33.595637],[-82.028238,33.544934],[-82.01655587044488,33.529055386425895],[-81.990938,33.494235],[-81.926336,33.462937],[-81.920121,33.410753],[-81.932737,33.343541],[-81.846136,33.303843],[-81.84650053235788,33.24725208542989],[-81.846536,33.241746],[-81.763535,33.203648],[-81.76250598279576,33.197265888297295],[-81.755135,33.15155],[-81.658433,33.103152],[-81.61595571078908,33.08933853936399],[-81.601655,33.084688],[-81.54396622431388,33.04439995414439],[-81.50203,33.015113],[-81.499566,32.943722],[-81.464069,32.897814],[-81.42062,32.831223],[-81.4131167951736,32.744261327961496],[-81.41267,32.739083],[-81.393818,32.653491],[-81.397106,32.605587],[-81.38690190269416,32.59896485389979],[-81.328753,32.561228],[-81.28423838176558,32.547110946284995],[-81.274927,32.544158],[-81.194829,32.465086],[-81.194931,32.411489],[-81.17347379448609,32.38490278088669],[-81.133032,32.334794],[-81.128034,32.276297],[-81.153531,32.237687],[-81.14759517045536,32.22716944659709],[-81.119361,32.177142],[-81.113334,32.113205],[-81.038265,32.084469],[-81.006745,32.101152],[-80.943226,32.057824],[-80.885517,32.0346],[-80.84313,32.024226],[-80.848441,31.988279],[-80.911207,31.943769],[-80.941359,31.912984],[-81.000317,31.856744],[-81.036873,31.812721],[-81.077057,31.761256],[-81.130634,31.722692],[-81.13529859020048,31.710564597966087],[-81.139394,31.699917],[-81.133493,31.623348],[-81.173079,31.555908],[-81.17483263659058,31.53959644949479],[-81.177254,31.517074],[-81.213493,31.462818],[-81.258616,31.404425],[-81.279338,31.351127],[-81.260958,31.30391],[-81.26437794808837,31.294599064745494],[-81.282842,31.24433],[-81.304957,31.206173],[-81.368241,31.136534],[-81.402096,31.125383],[-81.401267,31.072781],[-81.420474,31.016703],[-81.41251803557948,30.990834503508392],[-81.408484,30.977718],[-81.405153,30.908203],[-81.44013,30.821369],[-81.460061,30.769912],[-81.444124,30.709714],[-81.507218,30.722936],[-81.528281,30.723359],[-81.56171,30.715597],[-81.633273,30.729603],[-81.668283,30.744644],[-81.732238,30.749635],[-81.763384,30.773821],[-81.808543,30.790016],[-81.868624,30.792756],[-81.902354,30.82082],[-81.90597843940638,30.82140734150199],[-81.943187,30.827437],[-81.994992,30.786074],[-82.032667,30.750674],[-82.041834,30.692374],[-82.049529,30.655544],[-82.015728,30.601698],[-82.018381,30.531176],[-82.028232,30.447385],[-82.042011,30.403253],[-82.040766,30.370144],[-82.05098298168086,30.368367775944893],[-82.094709,30.360766],[-82.143306,30.363378],[-82.180043,30.36861],[-82.210318,30.424577],[-82.200965,30.474427],[-82.229427,30.520814],[-82.218607,30.564395],[-82.41898411217848,30.580916669731494],[-82.459581,30.584264],[-82.45979243541368,30.58427652830619],[-82.58400518641946,30.591636579087588],[-82.68952979847276,30.597889290641792],[-82.877311,30.609016],[-83.131431,30.623575],[-83.13661885820359,30.623885944893093],[-83.30934712159579,30.634238766671597],[-83.35771631362809,30.637137873134193],[-83.499951,30.645663],[-83.61170405882639,30.651560093708593],[-83.743729,30.65852691375049],[-83.820973,30.662603],[-84.007454,30.67206996846919],[-84.08375308229998,30.67594339796799],[-84.124993,30.678037],[-84.28551450903947,30.684809171948],[-84.38075418355248,30.688827197045892],[-84.474519,30.692783],[-84.812997,30.70965],[-84.86346384438247,30.711497014654395],[-84.864693,30.711542],[-84.91815,30.772082],[-84.934283,30.834033],[-84.935698,30.878703],[-84.983757,30.936984],[-85.006062,30.977039],[-85.002499,31.000682],[-85.011392,31.053546],[-85.02110756236277,31.075463872306393],[-85.035615,31.108192],[-85.107516,31.186451],[-85.108192,31.258591],[-85.089774,31.295026],[-85.08882996353047,31.30864775549659],[-85.087929,31.321648],[-85.092487,31.362881],[-85.066005,31.431363],[-85.071621,31.468384],[-85.05168142950619,31.51954032914169],[-85.041881,31.544684],[-85.05796,31.57084],[-85.058169,31.620227],[-85.12553,31.694965],[-85.11893,31.732664],[-85.12544057734247,31.76296870341829],[-85.12915931558317,31.780278268076593],[-85.141831,31.839261],[-85.114031,31.89336],[-85.067829,31.967358],[-85.06359054298467,31.991857],[-85.05141112791277,32.062256083621996],[-85.047063,32.087389],[-85.058749,32.136018],[-84.997765,32.185445],[-84.930127,32.219051],[-84.91994214792587,32.230848200933295],[-84.891841,32.263398],[-84.955704,32.30591],[-85.008096,32.336677],[-84.983466,32.363186],[-84.98115029413368,32.37904007668179],[-84.971831,32.442843],[-84.99978675631009,32.5070669687837],[-85.00113083912366,32.51015478839779],[-85.0071,32.523868],[-85.069848,32.583146],[-85.07607237260477,32.60806747515709],[-85.088533,32.657958],[-85.11425,32.730447],[-85.12453322275059,32.75162960675139],[-85.160963,32.826672],[-85.1844,32.861317],[-85.18611740178916,32.87013826997159],[-85.232441,33.108075],[-85.23244140518726,33.108077093933595],[-85.23659537125276,33.12954402825069],[-85.29434686434526,33.42799314636459],[-85.30494383322488,33.4827563368455],[-85.314048,33.529805],[-85.33811629990588,33.653114391601385],[-85.360532,33.767957],[-85.38667057377278,33.90170149400329],[-85.398871,33.964128],[-85.398871244842,33.964129286779496],[-85.42107317522878,34.080812652607186],[-85.429499,34.125095],[-85.46314082477578,34.28619098850549],[-85.47514728110428,34.34368465787619],[-85.502471,34.474526],[-85.51304422927326,34.52394647132369],[-85.52689481816098,34.58868569273349],[-85.53440525781537,34.62379033843579],[-85.561424,34.750079],[-85.58281233378527,34.86043547447759],[-85.595165,34.924171],[-85.605165,34.984678]]]}}, {"type":"Feature","properties":{"name":"Minnesota","income":{"1995":37483,"1996":39791,"1997":41591,"1998":45311,"1999":46153,"2000":49170,"2001":49619,"2002":50157,"2003":50750,"2004":51202,"2005":52048,"2006":54022,"2007":55664,"2008":57318,"2009":55621,"2010":55422,"2011":56944,"2012":58828,"2013":60664,"2014":61473,"2015":63459}},"geometry":{"type":"Polygon","coordinates":[[[-97.229039,49.000687],[-96.93096,48.999984],[-96.405408,48.999984],[-95.97539,48.999984],[-95.340962,48.99874],[-95.31988878347217,48.99875834401038],[-95.153711,48.998903],[-95.153309,49.18488],[-95.15333,49.309287],[-95.153314,49.384358],[-95.058404,49.35317],[-94.988908,49.368897],[-94.952111,49.368679],[-94.878454,49.333193],[-94.816222,49.320987],[-94.797244,49.214284],[-94.774228,49.124994],[-94.750221,49.099763],[-94.750218,48.999992],[-94.718932,48.999991],[-94.683069,48.883929],[-94.685681,48.840119],[-94.694312,48.789352],[-94.61901,48.737374],[-94.508862,48.700362],[-94.446604,48.6929],[-94.43020127923407,48.69830878552848],[-94.388848,48.711945],[-94.281797,48.705255],[-94.251169,48.683514],[-94.250191,48.656323],[-94.091244,48.643669],[-93.927004,48.63122],[-93.844008,48.629395],[-93.80527,48.570299],[-93.815178,48.526508],[-93.674568,48.516297],[-93.562062,48.528897],[-93.467504,48.545664],[-93.464308,48.591792],[-93.371156,48.605085],[-93.347528,48.62662],[-93.207398,48.642474],[-93.14242,48.624924],[-93.08845453528609,48.626814218496484],[-92.954876,48.631493],[-92.894687,48.594915],[-92.728046,48.53929],[-92.634931,48.542873],[-92.631117,48.508252],[-92.657101,48.466915],[-92.575636,48.440827],[-92.51491,48.448313],[-92.456325,48.414204],[-92.469948,48.351836],[-92.416285,48.295463],[-92.369174,48.220268],[-92.314665,48.240527],[-92.295668,48.278118],[-92.295412,48.323957],[-92.26228,48.354933],[-92.162161,48.363279],[-92.055228,48.359213],[-92.000133,48.321355],[-91.980772,48.247801],[-91.89347,48.237699],[-91.79728357990868,48.20577591545358],[-91.781182,48.200432],[-91.714931,48.19913],[-91.692366,48.11933],[-91.559272,48.108268],[-91.542512,48.053268],[-91.465499,48.06677],[-91.336578,48.069627],[-91.250112,48.084087],[-91.156107,48.140475],[-91.03555,48.189459],[-91.03253946126509,48.19057882189869],[-90.906829,48.237339],[-90.843624,48.243576],[-90.804207,48.177833],[-90.775962,48.122229],[-90.703702,48.096009],[-90.566113,48.12262],[-90.471019,48.106076],[-90.31723,48.103793],[-90.136191,48.112136],[-90.029626,48.087588],[-89.973433,48.02035],[-89.868153,47.989898],[-89.749314,48.023325],[-89.625087,48.011517],[-89.489226,48.014528],[-89.555015,47.974849],[-89.660616,47.951216],[-89.737539,47.918183],[-89.793539,47.891358],[-89.923649,47.862062],[-89.974296,47.830514],[-90.072025,47.811105],[-90.187636,47.77813],[-90.323446,47.753771],[-90.42139,47.73515],[-90.537105,47.703055],[-90.647837,47.656176],[-90.735927,47.624343],[-90.86827,47.5569],[-91.023124,47.464964],[-91.02312471770206,47.464963516060784],[-91.146958,47.381464],[-91.262512,47.27929],[-91.387021,47.187293],[-91.456965,47.139156],[-91.573817,47.089917],[-91.644564,47.026491],[-91.737098,46.982853],[-91.79399591208139,46.94278064714189],[-91.806851,46.933727],[-91.906483,46.891236],[-92.013405,46.833727],[-92.062088,46.804038],[-92.01529,46.706469],[-92.050819,46.710517],[-92.100255,46.734446],[-92.143338,46.731596],[-92.183091,46.695241],[-92.205492,46.664741],[-92.292192,46.663242],[-92.292371,46.495585],[-92.29275980242826,46.417219502879995],[-92.293619,46.244043],[-92.29383060857869,46.157321306495994],[-92.294033,46.074377],[-92.338239,46.052149],[-92.35176,46.015685],[-92.392681,46.01954],[-92.44963,46.002252],[-92.472761,45.972952],[-92.545682,45.970118],[-92.580565,45.94625],[-92.656125,45.924442],[-92.721128,45.883805],[-92.759458,45.835341],[-92.776496,45.790014],[-92.826013,45.73665],[-92.84074210662547,45.72939673446969],[-92.869689,45.715142],[-92.88669712440898,45.644148],[-92.887929,45.639006],[-92.881136,45.573409],[-92.801503,45.562854],[-92.756906,45.557499],[-92.728023,45.525652],[-92.686793,45.472271],[-92.646768,45.437929],[-92.658486,45.396058],[-92.698967,45.336374],[-92.74826767468588,45.29605938650979],[-92.761868,45.284938],[-92.76609140867366,45.210021702422694],[-92.766932,45.195111],[-92.74382347936557,45.123646262323],[-92.740509,45.113396],[-92.802911,45.065403],[-92.761904,45.022467],[-92.750802,44.941567],[-92.76702326575186,44.861976737097685],[-92.76711733435718,44.86151518587589],[-92.768574,44.854368],[-92.805287,44.768361],[-92.79236079967048,44.758983813697085],[-92.73162385130317,44.71492278525959],[-92.696491,44.689436],[-92.618025,44.61287],[-92.54928,44.577704],[-92.399281,44.558292],[-92.361518,44.558935],[-92.31693313340578,44.539276012202684],[-92.314071,44.538014],[-92.291005,44.485464],[-92.24536464900538,44.454251124351785],[-92.232472,44.445434],[-92.111085,44.413948],[-92.08452858049277,44.404614314800995],[-91.9636,44.362112],[-91.916191,44.318094],[-91.892698,44.231105],[-91.85449997529766,44.197226519552196],[-91.817302,44.164235],[-91.719097,44.128853],[-91.647873,44.064109],[-91.573283,44.026901],[-91.55921556303969,44.024209316581185],[-91.440536,44.001501],[-91.42356869981727,43.984296880322596],[-91.357426,43.917231],[-91.291002,43.852733],[-91.28765562736709,43.847065],[-91.243955,43.773046],[-91.25700015600567,43.72565873722238],[-91.273252,43.666623],[-91.252926,43.600363],[-91.232812,43.564842],[-91.217706,43.50055],[-91.491042,43.50069],[-91.61083500055437,43.500687846779286],[-91.73021699783769,43.50068570094609],[-91.824848,43.500684],[-92.07980199312827,43.50070488517658],[-92.178863,43.500713],[-92.44894795143777,43.50041498856269],[-92.55312809051877,43.50030003631229],[-92.553161,43.5003],[-92.870277,43.499548],[-93.02434790054187,43.49955616363],[-93.04919200781647,43.49955748002459],[-93.228861,43.499567],[-93.49735132522038,43.49953072451169],[-93.576728,43.49952],[-93.64853303117357,43.49953548967509],[-93.97076,43.499605],[-93.97076155852818,43.499605003207385],[-94.24796744155518,43.50017547670759],[-94.390597,43.500469],[-94.44284998971817,43.50047850765469],[-94.85455506761066,43.50055341915219],[-94.874235,43.500557],[-94.91461348471358,43.50059587298608],[-95.214938,43.500885],[-95.38778759402187,43.50047872890739],[-95.45443223866057,43.50032208525],[-95.486803,43.500246],[-95.834421,43.499966],[-95.86094620157228,43.49999288490559],[-96.05316283450999,43.50018770815748],[-96.198484,43.500335],[-96.45326,43.50039],[-96.453315,43.552299],[-96.45290957436626,43.84950689301839],[-96.45290957169317,43.849508852637186],[-96.45243585466946,44.19677954009509],[-96.45243582459547,44.196801586664996],[-96.452213,44.360149],[-96.45329131359868,44.543636801817996],[-96.45380669966707,44.63133583194799],[-96.45483051555378,44.80555020404578],[-96.45584011363358,44.97734524827999],[-96.45755349848498,45.26889792871839],[-96.457781,45.30761],[-96.47007760304926,45.32679964939229],[-96.482556,45.346273],[-96.521787,45.375645],[-96.562142,45.38609],[-96.617726,45.408092],[-96.675447,45.410216],[-96.710786,45.43693],[-96.742509,45.478723],[-96.781036,45.535972],[-96.83541916197808,45.58612869288079],[-96.843957,45.594003],[-96.851621,45.619412],[-96.82616,45.654164],[-96.745086,45.701576],[-96.672665,45.732336],[-96.630512,45.781157],[-96.587093,45.816445],[-96.571871,45.871846],[-96.563672,45.935245],[-96.574264,46.016545],[-96.57269749419397,46.02189167135768],[-96.554507,46.083978],[-96.59567,46.21985],[-96.60104,46.319554],[-96.647296,46.358499],[-96.709095,46.435294],[-96.744436,46.56596],[-96.78578618259849,46.629590849260886],[-96.78978651304978,46.63574667271669],[-96.790523,46.63688],[-96.786845,46.692805],[-96.788803,46.777575],[-96.763973,46.912507],[-96.833504,47.01011],[-96.819078,47.081152],[-96.82656912722827,47.150539],[-96.83600959454186,47.237981875487094],[-96.84022,47.276981],[-96.85748,47.440457],[-96.85595934905318,47.49917322952899],[-96.854073,47.57201],[-96.882376,47.649025],[-96.89349330133977,47.672126959443695],[-96.928506,47.744884],[-96.996364,47.844398],[-97.037354,47.933279],[-97.068987,48.026267],[-97.105616,48.091362],[-97.146745,48.168556],[-97.14584495947489,48.17322348299049],[-97.14191038719827,48.19362761887449],[-97.129533,48.257815],[-97.137904,48.344585],[-97.139173,48.430528],[-97.149122,48.532305],[-97.14810346613356,48.54074404618669],[-97.14772356830088,48.54389168365058],[-97.142915,48.583733],[-97.100009,48.667926],[-97.121253,48.713593],[-97.152588,48.772602],[-97.187362,48.867598],[-97.227854,48.945864],[-97.229039,49.000687]]]}}, {"type":"Feature","properties":{"name":"Alaska","income":{"1995":42255,"1996":44797,"1997":43657,"1998":47177,"1999":49133,"2000":51433,"2001":52332,"2002":51844,"2003":52391,"2004":52141,"2005":55477,"2006":58572,"2007":62854,"2008":67332,"2009":66712,"2010":63456,"2011":65699,"2012":66503,"2013":70058,"2014":70898,"2015":73391}},"geometry":{"type":"MultiPolygon","coordinates":[[[[179.481318,51.975301],[179.582857,52.016841],[179.636846,52.025712],[179.773922,51.970693],[179.743012,51.911749],[179.649484,51.87367],[179.543516,51.890926],[179.484634,51.921268],[179.481318,51.975301]]],[[[178.600493,51.655256],[178.6606,51.683065],[178.92533,51.623904],[179.195247,51.477871],[179.295785,51.419232],[179.41824,51.416195],[179.480418,51.36386],[179.253271,51.337239],[179.031533,51.449884],[178.930219,51.530089],[178.869249,51.556986],[178.7724,51.554119],[178.604866,51.616015],[178.600493,51.655256]]],[[[178.463385,51.987849],[178.552612,51.973968],[178.591597,51.952652],[178.539395,51.903246],[178.502493,51.899644],[178.432461,51.965533],[178.463385,51.987849]]],[[[178.204442,51.83089],[178.329699,51.836792],[178.378009,51.792626],[178.374074,51.747856],[178.270955,51.765186],[178.204442,51.83089]]],[[[178.093673,52.055141],[178.154769,52.061421],[178.201313,52.031502],[178.2009,51.991156],[178.120941,51.977012],[178.079214,52.01896],[178.093673,52.055141]]],[[[177.213086,51.920358],[177.310827,51.933273],[177.367363,51.968375],[177.460539,51.999751],[177.521006,52.063062],[177.581271,52.144927],[177.648654,52.1309],[177.675952,52.092167],[177.609087,52.028518],[177.572068,52.001812],[177.611553,51.950829],[177.601005,51.922254],[177.49928,51.922033],[177.409536,51.930821],[177.371263,51.901945],[177.334229,51.866769],[177.311768,51.825971],[177.262195,51.861891],[177.178789,51.879219],[177.213086,51.920358]]],[[[173.863992,52.792483],[174.067293,52.757637],[174.140115,52.750737],[174.158146,52.706059],[173.975116,52.707459],[173.819039,52.759805],[173.863992,52.792483]]],[[[173.439026,52.470528],[173.555739,52.479472],[173.638061,52.524209],[173.772799,52.509905],[173.702252,52.434804],[173.748301,52.392346],[173.725696,52.356579],[173.651293,52.35637],[173.543778,52.392666],[173.48638,52.368613],[173.319948,52.412058],[173.439026,52.470528]]],[[[172.458911,52.954548],[172.643266,53.004979],[172.792872,53.008568],[173.121988,52.990352],[173.251326,52.944362],[173.425362,52.868345],[173.423819,52.828799],[173.284417,52.827933],[173.204948,52.848911],[173.166899,52.795229],[173.096237,52.786782],[172.9826,52.79108],[172.903628,52.761667],[172.809387,52.78929],[172.763366,52.823656],[172.754236,52.87749],[172.669943,52.913011],[172.585075,52.921327],[172.472857,52.890234],[172.458911,52.954548]]],[[[-133.935016,55.920689],[-133.816363,55.964025],[-133.7314,56.028857],[-133.659241,56.083818],[-133.643817,56.127739],[-133.6721,56.222734],[-133.656889,56.281228],[-133.656415,56.326909],[-133.582116,56.352506],[-133.41837,56.332132],[-133.197009,56.333016],[-133.158233,56.314768],[-133.07823,56.246802],[-133.03996415325298,56.23905793430999],[-132.966922,56.224276],[-132.887585,56.172938],[-132.833864,56.103904],[-132.896433,56.099744],[-132.85963305440296,56.05257720308869],[-132.837592,56.024327],[-132.618464,55.911476],[-132.470697,55.782162],[-132.462531,55.673854],[-132.382505,55.665336],[-132.301119,55.55096],[-132.142945,55.457941],[-132.258056,55.416142],[-132.126398,55.288418],[-132.037122,55.275144],[-131.977397,55.180949],[-132.027513,55.104675],[-131.984592,55.027978],[-131.983324,54.897813],[-131.957914,54.791239],[-131.999591,54.731975],[-132.029747,54.701189],[-132.165182,54.69405],[-132.228223,54.72517],[-132.307943,54.718714],[-132.366389,54.751197],[-132.403533,54.784596],[-132.509371,54.781258],[-132.639032,54.753251],[-132.674324,54.674652],[-132.753019,54.673244],[-132.866355,54.700386],[-132.87721,54.753772],[-132.918751,54.783253],[-132.990589,54.820994],[-133.099047,54.919007],[-133.164788,54.976909],[-133.197719,55.033404],[-133.239695,55.092415],[-133.215086,55.136876],[-133.232491,55.198828],[-133.281979,55.217117],[-133.341259,55.205701],[-133.404497,55.214992],[-133.471938,55.247527],[-133.468217,55.281678],[-133.586605,55.3088],[-133.596762,55.218233],[-133.658359,55.232674],[-133.690174,55.304409],[-133.633006,55.361299],[-133.630945,55.416114],[-133.697898,55.454759],[-133.789055,55.457892],[-133.75287,55.544282],[-133.728549,55.593128],[-133.716665,55.660223],[-133.643324,55.729037],[-133.701152,55.78516],[-133.700468,55.837421],[-133.861039,55.848844],[-133.92025,55.860295],[-133.935016,55.920689]]],[[[-134.392983,56.864284],[-134.270459,56.93558],[-134.193751,56.933598],[-134.147103,56.95697],[-134.047753,56.923],[-134.006635,56.851587],[-133.942936,56.805551],[-133.86904,56.845938],[-133.921451,56.961511],[-134.049218,57.029203],[-134.008856,57.074578],[-133.887957,57.097744],[-133.739433,57.072184],[-133.536258,57.0387],[-133.334272,57.002442],[-133.317871026437,57.002674737699685],[-133.104611,57.005701],[-132.98137,56.92738],[-132.903211,56.80361],[-132.796602,56.776932],[-132.743207,56.71372],[-132.619258,56.660778],[-132.611326,56.599913],[-132.671154,56.543071],[-132.806838,56.505492],[-132.933042,56.5222],[-133.041726,56.518356],[-133.183493,56.454241],[-133.300571,56.462343],[-133.41508342926295,56.45646009323308],[-133.460634,56.45412],[-133.655468,56.442279],[-133.821628,56.391602],[-133.834555,56.319801],[-133.876624,56.275884],[-133.88114,56.223197],[-133.941986,56.180095],[-133.927725,56.145949],[-133.960525,56.091359],[-134.018043,56.088176],[-134.087446,56.094939],[-134.121868,56.029895],[-134.099805,55.98414],[-134.118062,55.914642],[-134.208251,55.876709],[-134.255096,55.844614],[-134.311763,55.812285],[-134.344652,55.846312],[-134.374965,55.928492],[-134.291804,55.926219],[-134.202178,56.035175],[-134.259749,56.13444],[-134.282212,56.254789],[-134.294679,56.335888],[-134.243126,56.395778],[-134.25192,56.44455],[-134.197967,56.531028],[-134.241938,56.555531],[-134.320134,56.554484],[-134.30112,56.620317],[-134.376274,56.668608],[-134.418534,56.822333],[-134.392983,56.864284]]],[[[-134.960502,58.403758],[-134.865084,58.357276],[-134.788441,58.28909],[-134.735829,58.234597],[-134.72359064048297,58.20965732961439],[-134.699956,58.161494],[-134.608911,58.171637],[-134.46176,58.159289],[-134.329872,58.13499],[-134.256223,58.144793],[-134.255797473354,58.144691601466484],[-134.174352,58.125284],[-134.183983,58.077295],[-134.138231,58.047103],[-134.087572,57.996475],[-133.999948,57.91481],[-133.904874,57.807406],[-133.896846,57.685524],[-133.808285,57.609604],[-133.8176,57.568353],[-133.871581,57.484158],[-133.866931,57.367869],[-133.786398,57.311528],[-133.840895,57.271074],[-133.875673,57.267613],[-133.983501,57.302838],[-134.100118,57.266285],[-134.193629,57.184879],[-134.302721,57.136562],[-134.378359,57.115016],[-134.386052,57.087392],[-134.443786,57.062292],[-134.497718,57.031194],[-134.565687,57.023737],[-134.634565,57.109863],[-134.640169,57.239852],[-134.55554,57.407428],[-134.607557,57.513042],[-134.695428,57.685335],[-134.709024,57.780498],[-134.752398,57.938956],[-134.783772,58.082292],[-134.864299,58.180489],[-134.958171,58.322057],[-134.960502,58.403758]]],[[[-136.563223,58.035052],[-136.538708,58.093482],[-136.446286,58.11334],[-136.365544,58.148854],[-136.387113,58.252414],[-136.290349,58.251761],[-136.176442,58.265111],[-136.033678,58.276728],[-135.877468,58.259852],[-135.78338,58.286709],[-135.712398,58.231892],[-135.497911,58.168882],[-135.275797,58.097024],[-135.108896,58.08827],[-134.950844,58.036993],[-134.926395,57.921919],[-135.004952,57.884338],[-134.95133740536397,57.78480125349048],[-134.939924,57.763612],[-134.824891,57.500067],[-134.825579,57.372143],[-134.854948,57.264766],[-134.738223,56.975741],[-134.695735,56.900791],[-134.663434,56.804687],[-134.62967,56.709596],[-134.615955,56.637289],[-134.626943,56.553868],[-134.669778,56.524129],[-134.64177,56.445479],[-134.634828,56.345297],[-134.634668,56.265832],[-134.653827,56.198385],[-134.674028,56.166925],[-134.763535,56.210363],[-134.810171,56.244987],[-134.839411,56.309403],[-134.915911,56.360555],[-134.977082,56.437294],[-135.058238,56.529453],[-135.123389,56.602823],[-135.175826,56.677876],[-135.21583,56.66534],[-135.305077,56.726382],[-135.362241,56.758742],[-135.467177,56.77141],[-135.550718,56.841228],[-135.506869,56.865978],[-135.476817,56.891232],[-135.442339,56.942355],[-135.353447,57.020905],[-135.457907,57.070165],[-135.571504,57.105697],[-135.604555,57.045834],[-135.63688,57.009874],[-135.825598,56.989032],[-135.856021,56.995636],[-135.844612,57.083568],[-135.755007,57.123972],[-135.753581,57.167168],[-135.832253,57.170647],[-135.870519,57.221639],[-135.837719,57.282068],[-135.85816,57.321358],[-135.892131,57.408048],[-135.943766,57.45878],[-136.047547,57.513762],[-136.088071,57.555291],[-136.163059,57.558861],[-136.238166,57.625991],[-136.250818,57.684831],[-136.304684,57.771051],[-136.371358700179,57.83166131938589],[-136.372377,57.832587],[-136.458829,57.853901],[-136.484259,57.89646],[-136.573288,57.926844],[-136.563223,58.035052]]],[[[-152.064099,60.417137],[-151.952456,60.510609],[-151.839194,60.485862],[-151.891542,60.440177],[-151.956263,60.367841],[-152.079995,60.341191],[-152.064099,60.417137]]],[[[-153.597411,59.386827],[-153.489005,59.41523],[-153.412493,59.415105],[-153.347772,59.377985],[-153.386898,59.33075],[-153.515286,59.320878],[-153.546695,59.331348],[-153.597411,59.386827]]],[[[-154.779663,57.366335],[-154.69331,57.446085],[-154.618704,57.514972],[-154.52206,57.577786],[-154.411385,57.598452],[-154.292471,57.644223],[-154.196959,57.664639],[-153.994572,57.656905],[-153.930279,57.696791],[-153.93522,57.813047],[-153.781408,57.876417],[-153.721176,57.890615],[-153.648798,57.880103],[-153.512024,57.909156],[-153.533204,57.941117],[-153.484603,57.9765],[-153.386422,57.936526],[-153.299009,57.985626],[-153.365574,58.039052],[-153.419783,58.059638],[-153.362281,58.106786],[-153.316127,58.14039],[-153.223709,58.16212],[-153.202801,58.20808],[-153.101841,58.257938],[-153.044316,58.306336],[-152.925586,58.339686],[-152.883107,58.400443],[-152.787776,58.411313],[-152.733845,58.460662],[-152.640313,58.469868],[-152.66622,58.544087],[-152.61613,58.601852],[-152.560171,58.61968],[-152.453817,58.618515],[-152.354709,58.63828],[-152.337212,58.589095],[-152.38761,58.52287],[-152.467197,58.476609],[-152.512483,58.427349],[-152.49848,58.372351],[-152.432235,58.355221],[-152.387343,58.359499],[-152.34486,58.39163],[-152.35609,58.42347],[-152.301713,58.428697],[-152.227835,58.376424],[-152.129257,58.396414],[-152.08925,58.367644],[-151.981781,58.347971],[-151.817111,58.263444],[-151.795696,58.211096],[-151.862321,58.168265],[-152.03412,58.183737],[-152.112205,58.148559],[-152.265111,58.135732],[-152.374399,58.120014],[-152.482674,58.129813],[-152.529036,58.093779],[-152.656801,58.061049],[-152.766673,58.029887],[-152.722524,57.987364],[-152.751978,57.933466],[-152.804807,57.899175],[-152.790211,57.858058],[-152.753437,57.834452],[-152.681204,57.875675],[-152.635378,57.91861],[-152.526283,57.913266],[-152.432608,57.976029],[-152.422573,57.948662],[-152.324103,57.916604],[-152.351152,57.834768],[-152.212247,57.791433],[-152.298762,57.745925],[-152.440182,57.72664],[-152.386805,57.667923],[-152.313974,57.63642],[-152.161617,57.623287],[-152.159677,57.593614],[-152.259641,57.527156],[-152.323683,57.467861],[-152.253603,57.384019],[-152.323687,57.34266],[-152.474883,57.434204],[-152.570527,57.448909],[-152.601148,57.382165],[-152.630441,57.322668],[-152.695698,57.281318],[-152.818187,57.265368],[-152.943463,57.256956],[-152.949333,57.187346],[-152.880321,57.164798],[-152.90054,57.132076],[-153.06433,57.10379],[-153.200217,57.042039],[-153.266822,56.999643],[-153.342018,56.982825],[-153.404263,57.080511],[-153.48652,57.085915],[-153.580831,57.049048],[-153.543429,56.995245],[-153.541492,56.887875],[-153.603624,56.887336],[-153.699409,56.855382],[-153.776468,56.830315],[-153.83964,56.822099],[-153.90215,56.771208],[-153.97178,56.744861],[-154.017042,56.689311],[-154.153147,56.681697],[-154.129017,56.742168],[-154.305713,56.846871],[-154.312888,56.918673],[-154.40749,56.968334],[-154.528538,57.001892],[-154.523432,57.129106],[-154.594977,57.257161],[-154.691855,57.28411],[-154.79384,57.288862],[-154.779663,57.366335]]],[[[-154.840415,56.42032],[-154.70614,56.521273],[-154.514078,56.604059],[-154.210336,56.609684],[-154.095833,56.617786],[-154.025041,56.572517],[-153.878764,56.565925],[-153.887678,56.533637],[-154.02093,56.482025],[-154.266332,56.496366],[-154.529507,56.502655],[-154.624282,56.475181],[-154.742887,56.401678],[-154.840415,56.42032]]],[[[-155.750002,55.821849],[-155.688098,55.864886],[-155.605373,55.928826],[-155.530591,55.912213],[-155.554245,55.84646],[-155.566307,55.789488],[-155.591002,55.761725],[-155.718593,55.772356],[-155.750002,55.821849]]],[[[-156.733628,56.077593],[-156.683003,56.09881],[-156.614757,56.065178],[-156.618202,56.017802],[-156.681814,55.994337],[-156.735292,56.02264],[-156.733628,56.077593]]],[[[-157.288702,56.566039],[-157.172027,56.598039],[-157.091146,56.581134],[-156.975549,56.540446],[-157.047173,56.519931],[-157.168777,56.53021],[-157.326059,56.525169],[-157.288702,56.566039]]],[[[-160.252749,54.913251],[-160.192058,55.038157],[-160.187261,55.118376],[-160.137102,55.171565],[-160.025257,55.203914],[-159.870591,55.284889],[-159.843859,55.249367],[-159.816419,55.178051],[-159.670305,55.182337],[-159.521096,55.253393],[-159.488766,55.188812],[-159.33847,55.046683],[-159.203228,54.914842],[-159.272354,54.864204],[-159.309681,54.865813],[-159.447982,54.941374],[-159.504434,55.027316],[-159.635226,55.037294],[-159.752779,55.066139],[-159.813625,55.027467],[-160.027035,55.02091],[-160.099295,54.962853],[-160.226967,54.864075],[-160.252749,54.913251]]],[[[-160.856621,55.318488],[-160.808929,55.370122],[-160.687442,55.402198],[-160.517513,55.379378],[-160.333421,55.436928],[-160.260565,55.463674],[-160.137032,55.450709],[-160.154038,55.377518],[-160.30655,55.303275],[-160.341217,55.251799],[-160.468262,55.288925],[-160.527617,55.256374],[-160.486511,55.181951],[-160.525226,55.129871],[-160.655577,55.160261],[-160.734942,55.151311],[-160.821381,55.117851],[-160.841917,55.20444],[-160.856621,55.318488]]],[[[-161.078486,58.635577],[-161.056595,58.702202],[-160.918586,58.746935],[-160.700627,58.817368],[-160.679309,58.780226],[-160.880515,58.581325],[-160.961416,58.553723],[-161.07563,58.549916],[-161.078486,58.635577]]],[[[-161.426005,55.216563],[-161.356726,55.221262],[-161.329875,55.219418],[-161.344152,55.158504],[-161.451286,55.178027],[-161.426005,55.216563]]],[[[-161.697129,55.249148],[-161.523434,55.271659],[-161.560207,55.207045],[-161.691553,55.198479],[-161.697129,55.249148]]],[[[-162.844362,54.510428],[-162.585315,54.447995],[-162.34484,54.401336],[-162.388754,54.367623],[-162.46695,54.342692],[-162.608608,54.369147],[-162.760247,54.372193],[-162.861736,54.424771],[-162.844362,54.510428]]],[[[-165.602225,54.045267],[-165.468221,54.079641],[-165.28077,54.115625],[-165.140978,54.131079],[-165.00791,54.134934],[-164.883134,54.196187],[-164.824183,54.225527],[-164.7637,54.223153],[-164.816166,54.158754],[-164.956139,54.060988],[-165.088283,54.072491],[-165.287665,54.038349],[-165.555768,54.023551],[-165.602225,54.045267]]],[[[-166.06155,54.185092],[-165.959751,54.220982],[-165.868192,54.214884],[-165.62555,54.298964],[-165.478452,54.295333],[-165.383719,54.196731],[-165.549217,54.112196],[-165.784434,54.069435],[-165.875129,54.03642],[-165.901649,54.06287],[-166.046438,54.044186],[-166.112242,54.122528],[-166.06155,54.185092]]],[[[-167.430619,60.197006],[-167.317602,60.231541],[-167.112841,60.231482],[-166.93866,60.214704],[-166.842599,60.21047],[-166.813127,60.249768],[-166.835825,60.268751],[-166.713539,60.327341],[-166.616566,60.319221],[-166.548589,60.361856],[-166.490358,60.389466],[-166.371874,60.355156],[-166.241032,60.38882],[-166.149763,60.4367],[-166.103296,60.367321],[-166.03734,60.319456],[-165.883086,60.343368],[-165.67987,60.292435],[-165.722533,60.236468],[-165.683554,60.198335],[-165.723484,60.163824],[-165.666679,60.124304],[-165.709223,60.066003],[-165.633879,60.019597],[-165.532633,59.953425],[-165.582302,59.908242],[-165.706609,59.883564],[-165.769832,59.900495],[-165.856822,59.869728],[-165.982317,59.871637],[-166.084995,59.839649],[-166.084282,59.776059],[-166.190406,59.750206],[-166.272168,59.811455],[-166.36213,59.838604],[-166.512819,59.846425],[-166.665528,59.878168],[-166.795194,59.913185],[-166.939572,59.965483],[-167.06578,59.98796],[-167.225739,60.04088],[-167.333289,60.066626],[-167.343509,60.126287],[-167.430619,60.197006]]],[[[-167.790928,53.33552],[-167.694484,53.388034],[-167.591219,53.393346],[-167.457366,53.442793],[-167.369791,53.450646],[-167.278827,53.478565],[-167.188033,53.524073],[-167.135695,53.551227],[-167.16164,53.605909],[-167.107836,53.633056],[-167.071823,53.66556],[-167.041245,53.707929],[-167.005778,53.755446],[-167.098135,53.799987],[-167.141966,53.826932],[-167.140992,53.866774],[-167.031252,53.945204],[-166.879488,53.988716],[-166.742587,54.015501],[-166.644627,54.014495],[-166.587393,53.959831],[-166.508388,53.923949],[-166.437083,53.955644],[-166.357117,54.002343],[-166.264519,53.97755],[-166.225644,53.986229105084995],[-166.172365,53.998124],[-166.075283,53.969571],[-166.16119973358198,53.93552905940859],[-166.210685,53.915922],[-166.250935,53.876851],[-166.320004,53.869527],[-166.404896,53.809345],[-166.336768,53.78709],[-166.198751,53.8361],[-166.113037,53.853716],[-166.09753,53.826933],[-166.138657,53.731082],[-166.244056,53.710708],[-166.320262,53.674276],[-166.444909,53.640646],[-166.508982,53.5838],[-166.581011,53.530449],[-166.656234,53.487119],[-166.749158,53.440944],[-166.878087,53.429884],[-166.994329,53.429201],[-167.075386,53.424979],[-167.166348,53.412793],[-167.291831,53.364102],[-167.308126,53.33433],[-167.417713,53.329856],[-167.488215,53.269121],[-167.539247,53.277864],[-167.622173,53.250362],[-167.747754,53.273564],[-167.851511,53.308668],[-167.790928,53.33552]]],[[[-168.12893,65.655744],[-167.979889,65.727972],[-167.650051,65.795703],[-167.282753,65.897386],[-166.768944,66.068582],[-166.038082,66.269512],[-165.407204,66.420441],[-164.816093,66.525025],[-164.400724,66.58111],[-164.39594359152198,66.58119763891509],[-163.824166,66.59168],[-163.603956,66.558089],[-163.728308,66.498552],[-163.798687,66.436875],[-163.873106,66.389015],[-163.849163,66.307639],[-163.843108,66.259869],[-163.925152,66.225078],[-163.916551,66.190494],[-163.80358,66.100059],[-163.695394,66.059552],[-163.495845,66.085388],[-163.372072,66.085029],[-163.146726,66.059487],[-162.997473,66.076845],[-162.750705,66.09016],[-162.622284,66.039526],[-162.423726,66.048984],[-162.331284,66.031403],[-162.137424,66.078547],[-161.838018,66.022582],[-161.775537,66.073732],[-161.613943,66.176693],[-161.548429,66.239912],[-161.484539,66.262426],[-161.341189,66.2551],[-161.320778,66.223591],[-161.198971,66.210949],[-160.993965,66.234444],[-161.089161,66.31514],[-161.322126,66.368554],[-161.575413,66.396806],[-161.694404,66.396174],[-161.916309,66.349481],[-161.86369,66.459487],[-161.87488,66.511446],[-162.105641,66.622584],[-162.175398,66.687789],[-162.349774,66.726713],[-162.501415,66.742503],[-162.626696,66.859572],[-162.582856,66.904292],[-162.466702,66.950998],[-162.468441,66.980604],[-162.63547,66.998434],[-162.842979,66.991177],[-163.011676,67.029538],[-163.299266,67.060748],[-163.591216,67.092373],[-163.702045,67.109375],[-163.74082,67.20996],[-163.878781,67.416125],[-164.051288,67.566351],[-164.256634,67.651651],[-164.533937,67.725606],[-165.094228,67.931963],[-165.35005,68.02586],[-165.39652029650296,68.03473051869818],[-165.688137,68.090396],[-165.872088,68.110047],[-165.97497,68.14091],[-166.089453,68.221299],[-166.313138,68.289164],[-166.60089,68.333637],[-166.838969,68.337186],[-166.591802,68.405551],[-166.328459,68.442261],[-166.28312,68.521247],[-166.229761,68.613771],[-166.193421,68.726649],[-166.224187,68.873175],[-165.923734,68.868432],[-165.522358,68.855839],[-164.967542,68.88303],[-164.526887,68.917909],[-164.253157,68.930938],[-163.926999,69.000802],[-163.574034,69.124077],[-163.244656,69.306081],[-163.151351,69.430262],[-163.151261,69.61263],[-163.071903,69.737605],[-162.989084,69.82525],[-162.78808,69.929097],[-162.503572,70.100393],[-162.302314,70.204227],[-161.879266,70.329269],[-161.581911,70.302877],[-161.288197,70.296772],[-160.81279,70.376696],[-160.214828,70.559087],[-159.869172,70.706397],[-159.648383,70.794368],[-159.17181,70.875103],[-159.114972,70.817402],[-158.85342,70.792352],[-158.573913,70.79495],[-158.366302,70.819712],[-158.032397,70.832263],[-157.768452,70.875842],[-157.421001,70.976805],[-157.176077,71.095549],[-156.906165,71.239616],[-156.809653,71.286886],[-156.56865,71.352561],[-156.531124,71.296338],[-156.309908,71.259881],[-156.074411,71.242489],[-156.044615,71.184701],[-155.895105,71.193899],[-155.587702,71.17256],[-155.520737,71.102476],[-155.533347,71.067683],[-155.705487,71.020153],[-155.762068,70.985644],[-155.95205,70.964831],[-155.979264,70.918524],[-155.924955,70.85272],[-155.731842,70.83116],[-155.543031,70.847175],[-155.485915,70.885905],[-155.513293,70.940579],[-155.36416,70.994195],[-155.262602,71.079149],[-155.060764,71.145422],[-154.942864,71.126264],[-154.581129,71.007321],[-154.608314,70.942405],[-154.572458,70.82594],[-154.430229,70.831258],[-154.290317,70.821495],[-154.127487,70.778133],[-153.89048,70.885719],[-153.666363,70.883448],[-153.426265,70.890131],[-153.23848,70.922467],[-153.049207,70.913102],[-152.904243,70.883877],[-152.696868,70.882086],[-152.423534,70.858708],[-152.223053,70.824594],[-152.19246,70.795294],[-152.348417,70.744382],[-152.352196,70.697802],[-152.473348,70.683669],[-152.433781,70.616926],[-152.29669,70.602287],[-152.078663,70.584504],[-151.975785,70.563215],[-151.697258,70.547741],[-151.734287,70.503492],[-151.739862,70.436207],[-151.504417,70.431103],[-151.297598,70.400748],[-151.175187,70.375558],[-151.020441,70.433841],[-150.903765,70.46091],[-150.786327,70.463271],[-150.557415,70.481643],[-150.414358,70.459694],[-150.301516,70.418392],[-150.074461,70.439333],[-149.866698,70.510769],[-149.740188,70.498151],[-149.461755,70.518271],[-149.179148,70.4857],[-148.928979,70.426835],[-148.667017,70.430084],[-148.477044,70.359068],[-148.46615,70.313609],[-148.351437,70.304453],[-148.203477,70.348188],[-147.9615,70.314201],[-147.863719,70.293317],[-147.765104,70.219806],[-147.431532,70.188826],[-147.233327,70.207553],[-147.161601,70.155612],[-146.991109,70.14761],[-146.885771,70.185917],[-146.508133,70.186044],[-146.129579,70.158948],[-146.006411,70.140402],[-145.858297,70.165996],[-145.623306,70.084375],[-145.43483,70.036994],[-145.175073,69.991707],[-144.902304,69.96451],[-144.792614,69.979796],[-144.672305,69.966876],[-144.455421,70.035244],[-144.274904,70.048711],[-143.914244,70.115696],[-143.5173,70.138418],[-143.425199,70.124928],[-143.281878,70.151052],[-142.99979,70.088305],[-142.746807,70.042531],[-142.452927,69.958125],[-142.404366,69.916511],[-142.239873,69.896598],[-142.015641,69.837976],[-141.713369,69.789497],[-141.43084,69.695144],[-141.210456,69.68419],[-141.002672,69.645609],[-141.00260959768698,68.49839100459099],[-141.002465,65.840075],[-141.00246492613797,65.8394210007989],[-141.00202022967997,61.90192202866048],[-141.00184966564296,60.39168800082828],[-141.00184,60.306105],[-140.53509,60.224224],[-140.472292,60.31059],[-139.989142,60.18524],[-139.698361,60.340421],[-139.086669,60.357654],[-139.082246,60.323825],[-139.200346,60.090701],[-139.046426,59.998235],[-138.702053,59.910245],[-138.643422,59.792502],[-138.584819,59.752453],[-137.604277,59.243057],[-137.498558,58.986694],[-137.526424,58.906834],[-137.52529495766598,58.90687226753729],[-137.447383,58.909513],[-137.264752,59.002352],[-136.863896,59.138472],[-136.826633,59.158389],[-136.581521,59.164909],[-136.48788291245395,59.262332415357186],[-136.466815,59.284252],[-136.474326,59.464194],[-136.358141,59.449799],[-136.234229,59.524731],[-136.23734,59.558734],[-136.350622,59.599326],[-136.190352,59.639854],[-135.945905,59.663802],[-135.72179346258997,59.72877903254028],[-135.477436,59.799626],[-135.231148,59.697176],[-135.214344,59.664343],[-135.114588,59.623415],[-135.027456,59.563692],[-135.026328,59.474658],[-135.067356,59.421855],[-135.010033,59.381288],[-135.029245,59.345364],[-134.961972,59.280376],[-134.702383,59.247836],[-134.66407,59.181172],[-134.566689,59.128278],[-134.481241,59.128071],[-134.379771,59.034961],[-134.401042,58.976221],[-134.327982,58.963431],[-134.328964,58.919593],[-134.250526,58.858046],[-133.840392,58.727991],[-133.699835,58.60729],[-133.379908,58.427909],[-133.461475,58.385526],[-133.343725,58.270915],[-133.176444,58.150151],[-133.076421,57.999762],[-132.869318,57.842941],[-132.756813,57.705093],[-132.65527865044697,57.60174461048348],[-132.559178,57.503927],[-132.367984,57.348685],[-132.252187,57.215655],[-132.371312,57.095229],[-132.051044,57.051155],[-132.11892319358697,56.89121697272269],[-132.125934,56.874698],[-131.871725,56.804965],[-131.90176,56.753158],[-131.835133,56.601849],[-131.581221,56.613275],[-131.461806,56.547904],[-131.167925,56.448361],[-131.087433314232,56.40741960071618],[-131.085704,56.40654],[-130.810707,56.371063],[-130.740619,56.342953],[-130.622482,56.267939],[-130.466874,56.239789],[-130.425575,56.140676],[-130.343716,56.127162],[-130.24554,56.096876],[-130.102761,56.116696],[-130.00426,55.993379],[-130.013198,55.916382],[-130.08451,55.823997],[-130.12372,55.80704],[-130.13824416414798,55.76296133152988],[-130.150061,55.727099],[-130.111677,55.682051],[-130.120132,55.563919],[-130.085413,55.491517],[-130.039928,55.429422],[-130.023558,55.338259],[-129.982348,55.302079],[-130.001735,55.264557],[-130.104749,55.188975],[-130.169294,55.105424],[-130.221512,55.02599],[-130.339504,54.921376],[-130.529228,54.8109],[-130.636745,54.778456],[-130.62807,54.739341],[-130.686192,54.71691],[-130.737423,54.753545],[-130.792122,54.784784],[-130.844145,54.765801],[-130.866866,54.769068],[-130.932454,54.806938],[-130.947338,54.886733],[-130.9604,54.933685],[-130.97503,54.974853],[-131.012061,54.996238],[-130.997057,55.044256],[-131.013215,55.090069],[-131.052298,55.11816],[-131.087497,55.163036],[-131.093806,55.191335],[-131.160492,55.197481],[-131.190628,55.108013],[-131.190033,55.043173],[-131.246018,54.989555],[-131.245988,54.940491],[-131.195197,54.919767],[-131.253671,54.866779],[-131.327624,54.859122],[-131.433473,54.896535],[-131.491504,54.930392],[-131.594567,54.93113],[-131.621948,54.946531],[-131.61087324495597,54.98588252108478],[-131.605661,55.004403],[-131.646276,55.035579],[-131.589387,55.08894],[-131.605302,55.107436],[-131.620261271871,55.10964822187079],[-131.748334,55.128588],[-131.828395,55.198482],[-131.862162,55.289284],[-131.854297,55.421074],[-131.844157,55.456742],[-131.971792,55.498279],[-132.114654,55.550623],[-132.183207,55.588128],[-132.20148784904697,55.63884575205138],[-132.224167,55.701766],[-132.265071,55.762174],[-132.130413,55.811419],[-132.067412,55.875078],[-132.170198,55.919231],[-132.279962,55.924839],[-132.323242,55.851878],[-132.397304,55.878867],[-132.449834,55.956186],[-132.492795,56.066436],[-132.594235,56.021858],[-132.708697,56.112124],[-132.718342,56.217704],[-132.843716,56.238933],[-132.877582,56.240322],[-132.926759,56.266188],[-132.961082,56.296167],[-133.029712,56.3157],[-133.070056,56.330951],[-133.0696,56.346323],[-133.060361,56.358378],[-132.977163,56.439673],[-132.896342,56.457978],[-132.791872,56.449169],[-132.627544,56.46287],[-132.528637,56.529269],[-132.45079,56.564098],[-132.529037,56.63797],[-132.542885,56.701905],[-132.54582226332,56.71362123587958],[-132.556758,56.757242],[-132.792089,56.856152],[-132.892388,56.993016],[-132.93752,57.048321],[-133.161448,57.086264],[-133.247414,57.136802],[-133.322359,57.112727],[-133.466932,57.159356],[-133.544817,57.24257],[-133.489738,57.305192],[-133.472039,57.368651],[-133.514964,57.473345],[-133.519598,57.530705],[-133.62076,57.578919],[-133.676449,57.625192],[-133.65453,57.713689],[-133.703097,57.792152],[-133.70880313739897,57.797764483718886],[-133.848776,57.93544],[-134.049603,58.062027],[-134.078155,58.152046],[-134.146685,58.199084],[-134.234572,58.197234],[-134.375579,58.208705],[-134.464635,58.227388],[-134.631203,58.247446],[-134.750586,58.391533],[-134.936897,58.457474],[-135.06423719858296,58.45123226565487],[-135.104413,58.449263],[-135.068437,58.374157],[-135.049062,58.309295],[-135.10121,58.292607],[-135.087872,58.200073],[-135.227736,58.2369],[-135.306507,58.242916],[-135.408059,58.342999],[-135.45583352463998,58.338517835625986],[-135.544213,58.330228],[-135.649861,58.324517],[-135.728054,58.397067],[-135.917917,58.381237],[-136.041818,58.380161],[-136.11193,58.34253],[-136.265906,58.314499],[-136.437152,58.302417],[-136.544776,58.316665],[-136.576799,58.277951],[-136.567956,58.245153],[-136.591924,58.217886],[-136.70125,58.219416],[-136.717093,58.273508],[-136.857605,58.31636],[-136.911713,58.370252],[-136.986384,58.404043],[-137.078109,58.397474],[-137.239366,58.453159],[-137.355328,58.492374],[-137.568216,58.587989],[-137.653709,58.608324],[-137.681633,58.656452],[-137.836448,58.741563],[-137.941828,58.794322],[-137.938546754526,58.803774349767075],[-137.924608,58.843928],[-137.951995,58.886029],[-138.066332,58.957126],[-138.224323,59.032216],[-138.357909,59.069394],[-138.636702,59.130585],[-138.807186,59.208772],[-138.919749,59.248531],[-139.07148,59.28715],[-139.271031,59.337421],[-139.420168,59.37976],[-139.632896,59.459906],[-139.861306,59.546678],[-139.74266,59.623871],[-139.585789,59.642765],[-139.588777,59.708968],[-139.608545,59.821961],[-139.776836,59.833835],[-139.871222,59.802611],[-140.080423,59.756299],[-140.176224,59.735965],[-140.242577,59.687888],[-140.4119,59.699649],[-140.792511,59.728573],[-140.922635,59.751687],[-141.156497,59.813582],[-141.392811,59.870028],[-141.485207,59.925024],[-141.595376,59.961905],[-141.73624,59.961905],[-141.912218,60.009779],[-142.062454,60.023781],[-142.426572,60.071066],[-142.744868,60.09413],[-142.908859,60.090328],[-143.0687,60.068603],[-143.267818,60.058655],[-143.624152,60.037257],[-143.781649,60.010354],[-143.885431593397,59.988392171256784],[-143.897029,59.985938],[-144.005879,60.012981],[-144.052539,60.041759],[-144.1103,60.098939],[-144.186745,60.116967],[-144.348913,60.091184],[-144.429249,60.14802],[-144.555093,60.178485],[-144.654899,60.204882],[-144.929327,60.228253],[-144.957848,60.288152],[-145.089139,60.320014],[-145.136728,60.296219],[-145.254749,60.311448],[-145.380064,60.352829],[-145.51081,60.318296],[-145.639204,60.301971],[-145.831202,60.350293],[-145.988546,60.387427],[-146.088134,60.364987],[-146.197229,60.348294],[-146.232681,60.338851],[-146.393256,60.327476],[-146.490804,60.294939],[-146.607692,60.241182],[-146.650852,60.242982],[-146.694034,60.279608],[-146.916487,60.290973],[-146.993353,60.24008],[-147.145205,60.171321],[-147.257795,60.107883],[-147.376397,60.016192],[-147.339794,59.962102],[-147.452217,59.954011],[-147.470281,59.906732],[-147.391846,59.87776],[-147.508309,59.841957],[-147.646045,59.817828],[-147.765122,59.795954],[-147.876475,59.763893],[-147.92924,59.783875],[-147.913316,59.837181],[-147.855084,59.871915],[-147.956775,59.9594],[-148.101239,59.952794],[-148.25406,59.932357],[-148.220554,59.97635],[-148.313962,60.033859],[-148.401666,59.977836],[-148.478881,59.935806],[-148.634777,59.915747],[-148.68591911504097,59.94280832785479],[-148.689496,59.944701],[-148.801325,59.952794],[-148.859556,59.924398],[-148.936406,59.953429],[-149.036467,59.942137],[-149.123262,59.968559],[-149.221067,59.938748],[-149.270623,59.872067],[-149.376593,59.835879],[-149.472227,59.903693],[-149.572714,59.852317],[-149.595531,59.79772],[-149.506758,59.770927],[-149.527793,59.706846],[-149.626311,59.73441],[-149.731966,59.706783],[-149.74622,59.637585],[-149.842672,59.7013],[-149.919444,59.691836],[-150.002337,59.630563],[-150.133747,59.556786],[-150.280838,59.466833],[-150.297108,59.424747],[-150.358992,59.399684],[-150.385341,59.341963],[-150.430144,59.343357],[-150.477717,59.422111],[-150.4989,59.456298],[-150.581182,59.445233],[-150.609488,59.386314],[-150.680872,59.305412],[-150.721799,59.292087],[-150.822768,59.330763],[-150.912817,59.305214],[-150.887821,59.26792],[-150.942212,59.233136],[-151.001196,59.224149],[-151.126247,59.209923],[-151.287771,59.219417],[-151.341601,59.222231],[-151.470623,59.242621],[-151.43339,59.135517],[-151.662368,59.089735],[-151.858124,59.144234],[-151.915684,59.227522],[-151.984101,59.278696],[-151.96313,59.344958],[-151.886513,59.421033],[-151.742915,59.468286],[-151.516339,59.52352],[-151.327803,59.573047],[-151.205459,59.630284],[-151.296895,59.696861],[-151.448669,59.648171],[-151.643061,59.646966],[-151.746815,59.686234],[-151.869468,59.769159],[-151.813619,59.844297],[-151.757693,59.917637],[-151.71801,60.009473],[-151.606881,60.099558],[-151.421702,60.212931],[-151.381959,60.296951],[-151.366874,60.372655],[-151.30609,60.387257],[-151.28181,60.496034],[-151.303125,60.561326],[-151.350154,60.63466],[-151.410273,60.711023],[-151.370515,60.733572],[-151.261319,60.769801],[-151.062558,60.787429],[-150.895508,60.853166],[-150.705812,60.937792],[-150.501923,61.007957],[-150.401859,61.036227],[-150.341709,61.024201],[-150.194128,60.90134],[-150.109276,60.890357],[-149.985374,60.879033],[-149.900135,60.940043],[-149.853693,60.967395],[-149.753183946415,60.99971962333039],[-149.717167,61.011303],[-149.831922,61.076197],[-150.005041,61.138556],[-150.065646,61.151079],[-150.265894,61.127365],[-150.228774,61.162581],[-150.22015374698398,61.19758435319138],[-150.204894,61.259548],[-150.425,61.245552],[-150.535997,61.269724],[-150.679902,61.265888],[-150.827295,61.22839],[-150.939251,61.210299],[-150.97184335367095,61.19545496070848],[-151.047736,61.16089],[-151.121692,61.083574],[-151.166606,61.046404],[-151.252384,61.039968],[-151.349004,61.010004],[-151.4803,61.010902],[-151.600126,60.965589],[-151.720815,60.904257],[-151.800264,60.853672],[-151.77731,60.810461],[-151.703802,60.732376],[-151.716379,60.710415],[-151.89792,60.72175],[-152.039381,60.660517],[-152.13616,60.578475],[-152.261497,60.538237],[-152.331365,60.473525],[-152.30195,60.414328],[-152.234199,60.393888],[-152.376743,60.345613],[-152.411281,60.287864],[-152.539843,60.241644],[-152.574938,60.206451],[-152.57873,60.16987],[-152.550177,60.113715],[-152.575153,60.04826],[-152.679402,59.968054],[-152.700822,59.920309],[-152.860867,59.875033],[-152.967267,59.881494],[-153.009084,59.830643],[-153.016353,59.751127],[-153.051559,59.691562],[-153.155019,59.654344],[-153.240018,59.632426],[-153.308837,59.625706],[-153.409422,59.636328],[-153.542466,59.630236],[-153.553163,59.597046],[-153.577828,59.555991],[-153.684925,59.552865],[-153.76148,59.543411],[-153.699025,59.463603],[-153.747201,59.429657],[-153.862199,59.424124],[-153.925307,59.405254],[-153.998506,59.384723],[-154.030807,59.32704],[-154.122681,59.287622],[-154.141192,59.216598],[-154.172944,59.172496],[-154.180691,59.123235],[-154.063489,59.07214],[-153.932824,59.062677],[-153.793972,59.071416],[-153.695664,59.073994],[-153.596489,59.000192],[-153.479939,58.995286],[-153.393101,58.951097],[-153.322843,58.907849],[-153.267407,58.867218],[-153.29739542924597,58.85370229945068],[-153.369389,58.821255],[-153.402472,58.742607],[-153.445002,58.70931],[-153.55265,58.687176],[-153.591635,58.640084],[-153.731019,58.608224],[-153.851432,58.611872],[-153.909994,58.561213],[-153.930473,58.497482],[-154.001918,58.492346],[-154.07066,58.440018],[-153.985416,58.390877],[-154.074145,58.352661],[-154.103412,58.280161],[-154.145277,58.210931],[-154.222465,58.132566],[-154.340449,58.090921],[-154.477979,58.052379],[-154.581547,58.019285],[-154.765287,58.00371],[-154.876559,58.027722],[-155.026275,57.999302],[-155.118648,57.953925],[-155.061806,57.90433],[-155.097095,57.865356],[-155.272917,57.823981],[-155.285339,57.758726],[-155.354011,57.715261],[-155.506533,57.76097],[-155.609353,57.777699],[-155.615203,57.688074],[-155.629912,57.656376],[-155.724167,57.633445],[-155.732779,57.549732],[-155.915261,57.535331],[-156.046804,57.525724],[-156.012841,57.451394],[-156.091668,57.439829],[-156.220105,57.445295],[-156.362039,57.400474],[-156.336427,57.336081],[-156.342943,57.248056],[-156.334404,57.1823],[-156.37428730155398,57.15925012072409],[-156.44301,57.119533],[-156.479111,57.068395],[-156.55052,56.98461],[-156.63784,56.993905],[-156.704216,56.987079],[-156.825982,56.897667],[-156.935629,56.920087],[-157.034624,56.884487],[-157.073453,56.838345],[-157.183636,56.769079],[-157.290511,56.804713],[-157.411488,56.778351],[-157.530765,56.753775],[-157.563802,56.703426],[-157.45216,56.64322],[-157.496523,56.616897],[-157.605231,56.621315],[-157.674587,56.609507],[-157.719048,56.653084],[-157.791844,56.670692],[-157.918541,56.643137],[-157.869897,56.566837],[-157.817826,56.51421],[-157.869124,56.456612],[-157.971711,56.476737],[-158.12744,56.460805],[-158.246144,56.466124],[-158.284699,56.481089],[-158.371953,56.467334],[-158.438414,56.427471],[-158.489546,56.341865],[-158.415095,56.336228],[-158.288369,56.316089],[-158.207387,56.294354],[-158.117797,56.230742],[-158.283191,56.173212],[-158.374324,56.134522],[-158.394922,56.064721],[-158.431471,55.994452],[-158.50984,55.979617],[-158.638211,55.994743],[-158.653214,55.958615],[-158.74856,55.959365],[-158.898116,55.951041],[-159.096187,55.91475],[-159.086217,55.834869],[-159.394595,55.714944],[-159.532754,55.676424],[-159.564401971435,55.63724485474748],[-159.572125,55.627684],[-159.696713,55.573306],[-159.733899,55.569985],[-159.760365,55.615203],[-159.679201,55.655895],[-159.673191,55.750961],[-159.627482,55.803248],[-159.679792,55.838765],[-159.770298,55.852357],[-159.847359,55.80253],[-159.937089,55.803306],[-160.026282,55.792295],[-160.058443,55.721734],[-160.130445,55.681419],[-160.279827,55.641384],[-160.392587,55.602771],[-160.464301,55.533243],[-160.462745,55.506654],[-160.521335,55.47442],[-160.654117,55.512596],[-160.666917,55.459776],[-160.781401,55.45178],[-160.836725,55.473135],[-160.976551,55.472736],[-161.080549,55.408498],[-161.253977,55.355896],[-161.486114,55.359322],[-161.514211,55.385254],[-161.478303,55.4406],[-161.469271,55.49683],[-161.376102,55.569794],[-161.392613,55.628221],[-161.482064,55.633979],[-161.587047,55.62006],[-161.658262,55.560447],[-161.700069,55.51439],[-161.686495,55.408041],[-161.777414,55.329377],[-161.863339,55.266989],[-161.817232,55.176529],[-161.718614,55.154166],[-161.576643,55.103831],[-161.550357,55.065734],[-161.690346,55.0785],[-161.792297,55.052278],[-161.906434,55.10032],[-161.956595,55.112174],[-162.053281,55.074212],[-162.11874,55.102911],[-162.190348,55.066981],[-162.219326,55.028975],[-162.235675,54.962601],[-162.236806,54.88163],[-162.282944,54.841216],[-162.349315,54.836049],[-162.428237,54.895434],[-162.435473,54.929249],[-162.41351,55.03656],[-162.471364,55.051932],[-162.569291,55.004599],[-162.587967,54.97201],[-162.708453,54.95848],[-162.834245,54.926851],[-162.913684,54.950273],[-162.962205,54.993538],[-163.065602,54.926172],[-163.14958,54.885906],[-163.254588,54.838907],[-163.352997,54.810174],[-163.281379,54.77673],[-163.184295,54.774912],[-163.068952,54.712605],[-163.037788,54.646995],[-163.223179,54.676895],[-163.392198,54.658496],[-163.572383,54.623211],[-163.80359,54.636498],[-164.03827,54.624688],[-164.257585,54.572722],[-164.337538,54.524259],[-164.352704,54.465023],[-164.456554,54.419856],[-164.640457,54.391166],[-164.743977,54.394216],[-164.861475,54.431353],[-164.904077,54.499195],[-164.944636,54.532903],[-164.948789,54.579877],[-164.864333,54.620188],[-164.741815,54.645441],[-164.674836,54.702596],[-164.576896,54.824564],[-164.57626,54.895342],[-164.43528,54.933126],[-164.343534,54.894139],[-164.204897,54.93124],[-164.119196,54.969416],[-163.994179,54.983315],[-163.894695,55.039115],[-163.774093,55.05578],[-163.527109,55.040871],[-163.429548,54.954759],[-163.343768,54.974439],[-163.280771,55.032959],[-163.314652,55.126312],[-163.132007,55.179629],[-163.032256,55.172147],[-162.86152,55.198339],[-162.900027,55.252466],[-162.813255,55.299458],[-162.64165,55.392576],[-162.565411,55.466849],[-162.365467,55.604586],[-162.219551,55.710867],[-162.120886,55.749089],[-162.05063,55.790897],[-161.898956,55.833464],[-161.807833,55.891954],[-161.712283,55.904232],[-161.450442,55.954485],[-161.15687,56.012216],[-160.964744,56.023754],[-160.807119,56.02398],[-160.811041,55.94723],[-160.793215,55.88596],[-160.564014,55.863719],[-160.508433,55.869379],[-160.457194,55.917233],[-160.533685,55.95995],[-160.589569,55.983048],[-160.488708,56.077214],[-160.405869,56.207938],[-160.385922,56.279706],[-160.222878,56.346868],[-160.146252,56.400176],[-159.985615,56.449743],[-159.828049,56.543935],[-159.534961,56.626529],[-159.219956,56.73953],[-158.972735,56.842138],[-158.89320784818497,56.809167533379984],[-158.853294,56.79262],[-158.744534,56.795112],[-158.656355,56.810012],[-158.646812,56.846992],[-158.686184,56.911555],[-158.679293,56.988625],[-158.531328,57.132156],[-158.32018,57.281558],[-158.229883,57.321534],[-158.083785,57.357181],[-157.931624,57.476208],[-157.772496,57.547055],[-157.678891,57.563888],[-157.684282,57.609974],[-157.709179,57.657459],[-157.683349,57.753695],[-157.642226,57.868777],[-157.596601,58.08867],[-157.556556,58.148445],[-157.48013,58.217354],[-157.547209,58.277535],[-157.541041,58.377302],[-157.481487,58.480771],[-157.313572,58.565043],[-157.24485909580898,58.609791],[-157.135927,58.680731],[-157.06223,58.740187],[-156.993548,58.836798],[-157.016088,58.86349],[-157.116866,58.867533],[-157.15324823205194,58.85920839833087],[-157.388651,58.805346],[-157.572524,58.750839],[-157.777937,58.703288],[-158.140307,58.61502],[-158.232276,58.619902],[-158.332093,58.665313],[-158.376873,58.748043],[-158.423828,58.769847],[-158.564833,58.802715],[-158.520327,58.857105],[-158.619684,58.911048],[-158.767748,58.864264],[-158.790378,58.804712],[-158.780136,58.75379],[-158.861207,58.69558],[-158.827852,58.626432],[-158.704052,58.482759],[-158.795316,58.408032],[-158.880927,58.39067],[-159.063346,58.423139],[-159.228398,58.603047],[-159.409779,58.773611],[-159.532347,58.833609],[-159.643549,58.845063],[-159.601899,58.884671],[-159.61612,58.931601],[-159.712114,58.929468],[-159.748183,58.875827],[-159.792923,58.823971],[-159.908386,58.779903],[-159.979344,58.835535],[-160.150528,58.866062],[-160.232788,58.901127],[-160.322922,58.953953],[-160.256592,58.99448],[-160.31778,59.070477],[-160.516426,59.01124],[-160.730971,58.921186],[-160.823489,58.829136],[-160.872003,58.878472],[-161.001101,58.849693],[-161.03450951839997,58.838808201815084],[-161.08615609474398,58.82198127900158],[-161.221942,58.777741],[-161.337982,58.742912],[-161.341328838373,58.73543103831018],[-161.372314,58.666172],[-161.550537,58.61116],[-161.751999,58.551842],[-161.802156,58.612318],[-162.027363,58.60705],[-162.171722,58.648441],[-161.994644,58.688828],[-161.824107,58.734549],[-161.764791,58.846235],[-161.804034,58.991717],[-161.910267,59.093503],[-161.996859,59.174126],[-162.048584,59.254177],[-161.992903,59.338385],[-161.848988,59.432494],[-161.790375,59.468197],[-161.70253,59.490906],[-161.772979,59.566243],[-161.873944,59.649487],[-161.88552,59.69839],[-162.046547,59.849688],[-162.108772,59.920107],[-162.143049,59.967506],[-162.228371,60.056313],[-162.37224,60.167009],[-162.45128,60.174367],[-162.49418,60.130271],[-162.495608,60.078949],[-162.487649,60.028082],[-162.515276,59.976183],[-162.622569,59.971809],[-162.737447,59.972254],[-162.808513,59.933933],[-162.929135,59.908054],[-163.172633,59.845058],[-163.458092,59.809958],[-163.772229,59.795624],[-163.930798,59.803853],[-164.133393,59.845612],[-164.208475,59.934461],[-164.178705,59.96181],[-164.13181,59.991177],[-164.272808,60.046194],[-164.411016,60.097675],[-164.517647,60.199493],[-164.619501,60.234938],[-164.698889,60.296298],[-164.777233,60.293833],[-164.984527,60.349929],[-165.129403,60.433707],[-165.069693,60.460893],[-165.015155,60.471414],[-164.956788,60.527837],[-164.986952,60.542406],[-165.093939,60.531862],[-165.190449,60.498001],[-165.274867,60.499021],[-165.362975,60.506866],[-165.420349,60.550692],[-165.367676,60.581158],[-165.206433,60.610227],[-165.073091,60.684217],[-164.991665,60.69884],[-165.010452,60.744789],[-165.040843,60.77266],[-165.030183,60.83805],[-165.08509,60.913763],[-165.10849499277896,60.926575398622894],[-165.194945,60.9739],[-165.133937,61.01125],[-165.057842,61.059746],[-165.139403,61.092946],[-165.203757,61.150341],[-165.325552,61.169306],[-165.385437,61.079574],[-165.459236,61.083424],[-165.55514,61.092674],[-165.640289,61.138066],[-165.63288,61.227965],[-165.623317,61.278431],[-165.787442,61.310063],[-165.831365,61.306719],[-165.921194,61.40308],[-165.877104,61.431149],[-165.791085,61.449852],[-165.746352,61.489304],[-165.865668,61.535046],[-165.912496,61.5562],[-165.999535,61.53972],[-166.075398,61.49298],[-166.149577,61.513288],[-166.211787,61.608373],[-166.143757,61.724352],[-166.050997,61.766689],[-166.094312,61.813859],[-165.940864,61.84908],[-165.803979,61.825685],[-165.639516,61.847006],[-165.650103,61.874153],[-165.743528,61.962533],[-165.754295,62.055955],[-165.672037,62.13989],[-165.458499,62.282847],[-165.26927,62.427352],[-165.096155,62.522452],[-165.052202,62.598217],[-164.962432,62.658246],[-164.837703,62.685267],[-164.864367,62.752042],[-164.87564,62.806254],[-164.813007,62.903919],[-164.685213,63.022191],[-164.607425,63.112899],[-164.442368,63.202672],[-164.209475,63.251472],[-164.066991,63.262276],[-163.885059,63.222308],[-163.73265,63.213257],[-163.616272,63.141213],[-163.529938,63.1354],[-163.316203,63.037763],[-163.053996,63.058334],[-162.919727,63.120153],[-162.844559,63.154191],[-162.821122,63.205596],[-162.72408,63.214615],[-162.59665194674793,63.28038731501158],[-162.526588,63.316551],[-162.42153,63.409014],[-162.352274,63.454069],[-162.562007,63.537105],[-162.707559,63.577607],[-162.587527,63.625115],[-162.401203,63.634367],[-162.252411,63.541753],[-162.073156,63.513768],[-161.982168,63.446313],[-161.676526,63.465003],[-161.421085,63.46015],[-161.191163,63.490072],[-161.073573,63.5617],[-160.783304,63.752893],[-160.76562,63.828714],[-160.900464,63.99834],[-160.941096,64.066319],[-160.962007,64.220575],[-161.177712,64.343541],[-161.263519,64.398166],[-161.504903,64.423074],[-161.469046,64.506575],[-161.389879,64.547833],[-161.198029,64.496626],[-160.992894,64.541295],[-160.793356,64.619317],[-160.783398,64.71716],[-160.935974,64.82237],[-161.079718,64.869549],[-161.133062,64.898219],[-161.213756,64.883324],[-161.327848,64.829836],[-161.376985,64.773036],[-161.518211,64.75325],[-161.64552,64.776452],[-161.772978,64.749258],[-161.878363,64.709476],[-162.060291,64.692872],[-162.188146,64.672395],[-162.234477,64.619336],[-162.539996,64.530931],[-162.603236,64.479904],[-162.632242,64.385734],[-162.768424,64.333516],[-162.83654,64.436702],[-162.857562,64.49978],[-162.940776,64.542417],[-163.033231,64.519314],[-163.027158,64.477945],[-163.091486,64.437736],[-163.133172,64.381844],[-163.249092,64.456223],[-163.4129,64.524986],[-163.686337,64.568798],[-163.829739,64.574965],[-163.974352,64.55137],[-164.147059,64.564552],[-164.307273,64.561488],[-164.548298,64.516738],[-164.807747,64.449432],[-165.001961,64.433917],[-165.291644,64.480731],[-165.819595,64.540171],[-166.236939,64.583558],[-166.413926,64.651229],[-166.482682,64.755101],[-166.478978,64.797036],[-166.407315,64.852281],[-166.432246,64.88316],[-166.586066,64.955712],[-166.697808,64.991201],[-166.73725,65.027526],[-166.911922,65.125965],[-166.886677,65.138763],[-166.634449,65.125873],[-166.479913,65.167249],[-166.451711,65.236178],[-166.347189,65.276341],[-166.439404,65.319058],[-166.596964,65.336246],[-166.750702,65.333172],[-166.899681,65.360642],[-167.067707,65.385117],[-167.348739,65.397891],[-167.474024,65.412744],[-167.684378,65.489079],[-167.851234,65.538181],[-168.04762,65.569149],[-168.12893,65.655744]]],[[[-169.28652,52.784747],[-169.044466,52.893927],[-168.95946,52.936739],[-168.861061,53.016384],[-168.785236,53.045038],[-168.804901,53.120015],[-168.763331,53.182812],[-168.581891,53.286521],[-168.445083,53.26533],[-168.420521,53.322743],[-168.395355,53.397776],[-168.342127,53.475992],[-168.238321,53.521902],[-168.027006,53.562755],[-167.914669,53.522716],[-167.789164,53.519329],[-167.808117,53.473861],[-167.856837,53.428609],[-167.842328,53.386489],[-167.959096,53.341788],[-168.092011,53.28827],[-168.296229,53.227235],[-168.343075,53.170553],[-168.412522,53.110683],[-168.457103,53.055839],[-168.613964,53.008776],[-168.688468,52.9664],[-168.755531,52.907507],[-168.851017,52.90804],[-169.005038,52.829992],[-169.170371,52.776663],[-169.261765,52.754897],[-169.28652,52.784747]]],[[[-169.81831,56.633612],[-169.613691,56.622761],[-169.474322,56.625183],[-169.453786,56.583786],[-169.582624,56.536939],[-169.685825,56.539717],[-169.81831,56.633612]]],[[[-170.170683,52.784918],[-170.092221,52.919387],[-170.026342,52.944912],[-169.857567,52.908533],[-169.76274,52.97805],[-169.820198,53.06679],[-169.747457,53.0932],[-169.680033,53.035075],[-169.662385,52.951752],[-169.666512,52.864349],[-169.703873,52.777117],[-169.818548,52.791577],[-169.951498,52.788615],[-170.077734,52.720416],[-170.207887,52.708899],[-170.170683,52.784918]]],[[[-170.420047,57.212917],[-170.303091,57.238029],[-170.143996,57.242804],[-170.133884,57.181329],[-170.286318,57.128169],[-170.421867,57.161202],[-170.420047,57.212917]]],[[[-170.817943,52.636275],[-170.671545,52.698082],[-170.532144,52.679971],[-170.58496,52.587186],[-170.685914,52.581228],[-170.788495,52.54024],[-170.841936,52.558171],[-170.817943,52.636275]]],[[[-171.312658,52.493502],[-171.256768,52.52858],[-171.196013,52.500106],[-171.226729,52.434269],[-171.30417,52.449952],[-171.312658,52.493502]]],[[[-171.83683,63.564883],[-171.791881,63.620625],[-171.802824,63.716391],[-171.743398,63.782971],[-171.613182,63.785065],[-171.58305,63.715557],[-171.552856,63.666251],[-171.309333,63.621085],[-170.950817,63.570127],[-170.859032,63.587503],[-170.606282,63.672732],[-170.488192,63.696723],[-170.344855,63.694225],[-170.26748,63.675816],[-170.176413,63.625489],[-170.095833,63.612701],[-170.048963,63.537958],[-170.007943,63.475428],[-169.857078,63.441975],[-169.656474,63.429929],[-169.566562,63.388725],[-169.462733,63.360458],[-169.087914,63.340937],[-168.937385,63.333789],[-168.685145,63.296427],[-168.751537,63.217962],[-168.841654,63.153844],[-168.93915,63.137653],[-169.07503,63.177689],[-169.230523,63.172948],[-169.436748,63.113579],[-169.534984,63.074355],[-169.576965,63.027025],[-169.568016,62.976879],[-169.638309,62.937527],[-169.757249,62.960087],[-169.788466,63.043015],[-169.88123,63.105848],[-170.049622,63.163377],[-170.186485,63.181618],[-170.263032,63.179147],[-170.30363,63.238692],[-170.430656,63.314284],[-170.663536,63.376109],[-170.896167,63.417745],[-171.067663,63.424579],[-171.226326,63.395108],[-171.285411,63.366464],[-171.433319,63.307578],[-171.528084,63.324933],[-171.667115,63.356166],[-171.760112,63.381633],[-171.849984,63.485039],[-171.83683,63.564883]]],[[[-172.612274,52.306828],[-172.545116,52.357863],[-172.448182,52.391439],[-172.326444,52.366472],[-172.301445,52.329951],[-172.414419,52.27674],[-172.528095,52.254336],[-172.639992,52.244765],[-172.612274,52.306828]]],[[[-173.074642,60.704657],[-172.912636,60.604129],[-172.847344,60.516742],[-172.545912,60.412225],[-172.380946,60.382764],[-172.238862,60.336642],[-172.254263,60.297375],[-172.416534,60.314347],[-172.630272,60.334922],[-172.895998,60.450587],[-173.0638,60.502589],[-173.115569,60.658971],[-173.074642,60.704657]]],[[[-175.301556,52.055602],[-175.031213,52.092109],[-174.887242,52.128602],[-174.715205,52.127375],[-174.55467,52.160405],[-174.462962,52.213031],[-174.455979,52.31369],[-174.329818,52.373548],[-174.185347,52.417788],[-174.068248,52.390331],[-173.985203,52.3176],[-174.046994,52.236262],[-174.022638,52.133713],[-173.899966,52.139949],[-173.654404,52.146192],[-173.529923,52.159364],[-173.375229,52.108228],[-173.174403,52.126278],[-172.947811,52.107371],[-172.980222,52.064049],[-173.169557,52.04385],[-173.39397,52.028674],[-173.513047,52.02531],[-173.695316,52.055319],[-173.820692,52.043312],[-173.901075,52.049435],[-174.099836,52.072078],[-174.278279,52.089489],[-174.382661,52.081658],[-174.408693,52.012811],[-174.556278,52.036733],[-174.736592,52.007308],[-174.892306,52.019687],[-175.014807,52.007],[-175.155673,52.011512],[-175.323322,52.007488],[-175.301556,52.055602]]],[[[-176.950128,51.686719],[-176.917088,51.797016],[-176.781889,51.832373],[-176.762478,51.867878],[-176.810433,51.927089],[-176.774023,51.965895],[-176.698771,51.964454],[-176.579975,52.003238],[-176.549119,51.955561],[-176.554661,51.909834],[-176.576381,51.842275],[-176.431673,51.861169],[-176.311573,51.872463],[-176.173871,51.882449],[-176.168643,51.948025],[-176.183023,51.998904],[-176.211188,52.064706],[-176.14951,52.11757],[-176.055983,52.109469],[-176.007589,52.066228],[-175.887514,51.995142],[-175.807848,51.989665],[-175.664274,51.993862],[-175.45047,52.012742],[-175.424859,51.972332],[-175.639739,51.933645],[-175.789118,51.919323],[-175.963041,51.846253],[-175.998464,51.801542],[-176.158185,51.768901],[-176.289921,51.741678],[-176.46705,51.726668],[-176.543948,51.698719],[-176.656005,51.658306],[-176.715424,51.620422],[-176.809,51.616235],[-176.938917,51.590982],[-176.987383,51.606872],[-176.950128,51.686719]]],[[[-177.670119,51.743381],[-177.492124,51.770306],[-177.313149,51.778223],[-177.228177,51.803783],[-177.199539,51.910239],[-177.181271,51.943167],[-177.099266,51.936119],[-177.04509,51.898605],[-177.098661,51.829647],[-177.105188,51.719333],[-177.18994,51.697217],[-177.275121,51.68051],[-177.34801,51.696513],[-177.483959,51.682278],[-177.651386,51.653604],[-177.707802,51.703268],[-177.670119,51.743381]]],[[[-178.19709,51.905464],[-178.090632,51.919399],[-177.952094,51.915348],[-177.887423,51.85089],[-177.757429,51.847042],[-177.615311,51.85508],[-177.649278,51.801851],[-177.755022,51.772834],[-177.827524,51.712086],[-177.86796,51.679374],[-177.909185,51.596671],[-178.04566,51.630062],[-178.117864,51.677831],[-178.054798,51.704768],[-177.98163,51.715617],[-177.995272,51.781535],[-178.086074,51.808047],[-178.224129,51.864881],[-178.19709,51.905464]]],[[[-178.889347,51.570352],[-178.678149,51.62601],[-178.551475,51.610175],[-178.584789,51.56386],[-178.734585,51.542326],[-178.825956,51.547085],[-178.889347,51.570352]]],[[[-178.876843,51.837917],[-178.779657,51.851547],[-178.733355,51.783947],[-178.792409,51.746071],[-178.895958,51.779219],[-178.876843,51.837917]]],[[[-179.174265,51.279057],[-178.995591,51.414484],[-178.926874,51.38364],[-178.908883,51.340582],[-179.07232,51.250963],[-179.126856,51.219862],[-179.174265,51.279057]]]]}}, {"type":"Feature","properties":{"name":"California","income":{"1995":36767,"1996":38691,"1997":39595,"1998":41003,"1999":43924,"2000":46836,"2001":47064,"2002":47323,"2003":48440,"2004":49894,"2005":53627,"2006":56646,"2007":59928,"2008":61017,"2009":58925,"2010":57664,"2011":57275,"2012":58322,"2013":60185,"2014":61927,"2015":64483}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-118.593969,33.467198],[-118.484785,33.487483],[-118.370323,33.409285],[-118.286261,33.351463],[-118.325244,33.299075],[-118.374768,33.320065],[-118.465368,33.326056],[-118.482609,33.369914],[-118.563442,33.434381],[-118.593969,33.467198]]],[[[-118.594033,33.035951],[-118.540069,32.980933],[-118.446771,32.895424],[-118.353504,32.821962],[-118.425634,32.800595],[-118.487908,32.84459],[-118.581513,32.931672],[-118.641578,33.017129],[-118.594033,33.035951]]],[[[-119.578942,33.278628],[-119.510489,33.307269],[-119.427171,33.266023],[-119.429559,33.228167],[-119.464725,33.215432],[-119.545872,33.233406],[-119.578942,33.278628]]],[[[-119.916216,34.058351],[-119.857304,34.071298],[-119.739472,34.049299],[-119.5667,34.053452],[-119.47073665694398,34.053996622103995],[-119.442654,34.054156],[-119.364214,34.050794],[-119.363065,34.000548],[-119.391587,33.994636],[-119.48771955738198,33.996515154389286],[-119.554472,33.99782],[-119.662825,33.985889],[-119.721206,33.959583],[-119.795938,33.962929],[-119.873358,33.980375],[-119.876916,34.023527],[-119.916216,34.058351]]],[[[-120.368278,34.076465],[-120.24248,34.057172],[-120.135853,34.026087],[-120.055107,34.037729],[-119.984316,33.983948],[-119.973691,33.942481],[-120.049682,33.914563],[-120.121817,33.895712],[-120.179049,33.927994],[-120.200085,33.956904],[-120.36484,33.991781],[-120.454134,34.028081],[-120.368278,34.076465]]],[[[-124.387023,40.504954],[-124.301355,40.659643],[-124.176715,40.843618],[-124.118147,40.989263],[-124.125448,41.048504],[-124.154513,41.087159],[-124.163988,41.138675],[-124.122677,41.189726],[-124.092284,41.287695],[-124.063076,41.439579],[-124.06747365942198,41.46473618849088],[-124.081987,41.547761],[-124.116037,41.628849],[-124.143479,41.709284],[-124.154246,41.728801],[-124.19104,41.736079],[-124.245027,41.7923],[-124.219592,41.846432],[-124.203402,41.940964],[-124.211605,41.99846],[-124.001188,41.996146],[-123.82203759858797,41.995620816946996],[-123.656998,41.995137],[-123.51911283680398,41.999172518032886],[-123.43477,42.001641],[-123.347562,41.999108],[-123.23100126057798,42.00497006225599],[-123.145959,42.009247],[-123.045254,42.003049],[-122.80008,42.004071],[-122.501135,42.00846],[-122.289749096157,42.00776473049658],[-122.289527,42.007764],[-122.101922,42.005766],[-121.846712,42.00307],[-121.675348,42.000351],[-121.44753999804797,41.99719003327258],[-121.43961,41.99708],[-121.251099,41.99757],[-121.035195,41.993323],[-120.87992571023597,41.993483259984885],[-120.692219,41.993677],[-120.501069,41.993785],[-120.181563,41.994588],[-119.999168,41.99454],[-119.999276,41.874891],[-119.99828,41.618765],[-119.999866,41.183974],[-119.999231,40.865899],[-119.997533,40.720992],[-119.996155,40.32125],[-119.997124,40.126363],[-119.997634,39.956505],[-119.99993544808497,39.72240692472418],[-120.00174,39.538852],[-120.00302891965698,39.44504577616049],[-120.00479551230397,39.31647501195848],[-120.005142,39.291258],[-120.00336402883298,39.16562676406879],[-120.00261484291299,39.11268937409578],[-120.00197525086698,39.06749587446829],[-120.001014,38.999574],[-119.904315,38.933324],[-119.587679,38.714734],[-119.58540614483898,38.713150900671195],[-119.32870452107596,38.534351927797495],[-119.279262,38.499914],[-119.157226100872,38.41439197176128],[-118.949673,38.26894],[-118.500958,37.949019],[-118.42799532515699,37.896224280909784],[-118.022181,37.602583],[-117.83350404414396,37.46493876624449],[-117.68061,37.353399],[-117.244917,37.030244],[-117.166000564031,36.97120753859029],[-117.000895,36.847694],[-116.488233,36.459097],[-116.375875,36.372562],[-116.093601,36.155805],[-115.892975,35.999967],[-115.84611392276199,35.96355267311089],[-115.64803201962498,35.80962921260289],[-115.647683,35.809358],[-115.404537,35.617605],[-115.303743,35.538207],[-115.160068,35.424129],[-115.043812,35.332012],[-114.804249,35.139689],[-114.633487,35.001857],[-114.629769,34.94304],[-114.634382,34.87289],[-114.576452,34.8153],[-114.490971,34.724848],[-114.465246,34.691202],[-114.422382,34.580711],[-114.378223,34.516521],[-114.378852,34.450376],[-114.335372,34.450038],[-114.264317,34.401329],[-114.172845,34.344979],[-114.14093,34.305919],[-114.14081715127998,34.30312751388169],[-114.139055,34.259538],[-114.17805,34.239969],[-114.229715,34.186928],[-114.292806,34.166725],[-114.348052,34.134458],[-114.405941,34.11154],[-114.428026,34.092787],[-114.43009113851998,34.07893140627949],[-114.435504,34.042615],[-114.454807,34.010968],[-114.509568,33.957264],[-114.534987,33.928499],[-114.508708,33.90064],[-114.505638,33.864276],[-114.520465,33.827778],[-114.504863,33.760465],[-114.496565,33.719155],[-114.504993,33.693022],[-114.525201,33.661583],[-114.529186,33.60665],[-114.524599,33.552231],[-114.597283,33.490653],[-114.62914651818897,33.43354499999979],[-114.635183,33.422726],[-114.673901,33.418299],[-114.725282,33.405048],[-114.707348,33.376628],[-114.707962,33.323421],[-114.723259,33.288079],[-114.674491,33.255597],[-114.678097,33.2303],[-114.679359,33.159519],[-114.706175,33.105335],[-114.670803,33.037984],[-114.628293,33.031052],[-114.575161,33.036542],[-114.51706679028098,33.024628763568494],[-114.511343,33.023455],[-114.481315,32.972064],[-114.47664,32.923628],[-114.463127,32.901884],[-114.468971,32.845155],[-114.531746,32.782503],[-114.570675,32.747417],[-114.61738652396197,32.74105277317659],[-114.667493,32.734226],[-114.705717,32.741581],[-114.719633,32.718763],[-115.000802,32.699676],[-115.465164,32.6671],[-116.04662,32.623353],[-116.10617888905,32.61857814263559],[-116.540643,32.583747],[-116.62705,32.576261],[-116.857154,32.557459],[-117.124862,32.534156],[-117.13203895573798,32.58560118738209],[-117.136664,32.618754],[-117.168866,32.671952],[-117.17719654844998,32.67699762339179],[-117.196767,32.688851],[-117.246069,32.669352],[-117.255169,32.700051],[-117.25497,32.786948],[-117.280971,32.822247],[-117.28217,32.839547],[-117.27387,32.851447],[-117.262905,32.849349],[-117.25617,32.859447],[-117.25616053514898,32.85967359410169],[-117.25447,32.900146],[-117.27213942717798,32.97552458254879],[-117.28077,33.012343],[-117.315278,33.093504],[-117.362572,33.168437],[-117.445583,33.268517],[-117.547693,33.365491],[-117.59588,33.386629],[-117.59618868573698,33.38696499431989],[-117.645582,33.440728],[-117.715349,33.460556],[-117.726486,33.483427],[-117.732258297614,33.48795502397859],[-117.814188,33.552224],[-117.840289,33.573523],[-117.927091,33.605521],[-118.000593,33.654319],[-118.088896,33.729817],[-118.11507672288198,33.74380332289499],[-118.132698,33.753217],[-118.1837,33.736118],[-118.231926185873,33.71529546782749],[-118.258687,33.703741],[-118.317205,33.712818],[-118.33329589297698,33.721184835257695],[-118.354705,33.732317],[-118.396606,33.735917],[-118.428407,33.774715],[-118.394307,33.804315],[-118.412708,33.883913],[-118.460611,33.969111],[-118.519514,34.027509],[-118.603572,34.039048],[-118.679366,34.033255],[-118.744952,34.032103],[-118.805114,34.001239],[-118.854653,34.034215],[-118.94447951145897,34.046738953350996],[-118.954722,34.048167],[-119.069959,34.09047],[-119.109784,34.094566],[-119.227743,34.161728],[-119.257043,34.213304],[-119.270144,34.252903],[-119.27661425185897,34.256340425014294],[-119.313034,34.275689],[-119.37578,34.321118],[-119.461036,34.374064],[-119.47794670672397,34.37883755877559],[-119.536957,34.395495],[-119.616862,34.420995],[-119.684666,34.408297],[-119.709067,34.395397],[-119.785871,34.415997],[-119.835771,34.415796],[-119.873971,34.408795],[-119.971951,34.444641],[-120.050682,34.461651],[-120.141165,34.473405],[-120.295051,34.470623],[-120.451425,34.447094],[-120.511421,34.522953],[-120.550092,34.542794],[-120.581293,34.556959],[-120.622575,34.554017],[-120.645739,34.581035],[-120.60197,34.692095],[-120.614852,34.730709],[-120.62632,34.738072],[-120.610266,34.85818],[-120.670835,34.904115],[-120.65030521183999,34.9751663022687],[-120.63357,35.033085],[-120.629583,35.078362],[-120.635787,35.123805],[-120.675074,35.153061],[-120.714185,35.175998],[-120.756086,35.160459],[-120.846674,35.204429],[-120.89679,35.247877],[-120.87957,35.294184],[-120.862133,35.360763],[-120.884757,35.430196],[-120.955863,35.453743],[-121.003359,35.46071],[-121.11424,35.57172],[-121.166712,35.635399],[-121.272322,35.666711],[-121.314632,35.71331],[-121.332449,35.783106],[-121.34705395600398,35.795186203814595],[-121.406823,35.844623],[-121.462264,35.885618],[-121.4862,35.970348],[-121.531876,36.014368],[-121.574602,36.025156],[-121.622009,36.099695],[-121.680145,36.165818],[-121.779851,36.227407],[-121.826425,36.24186],[-121.888491,36.30281],[-121.903195,36.393603],[-121.9416,36.485602],[-121.970427,36.582754],[-121.923866,36.634559],[-121.860604,36.611136],[-121.814462,36.682858],[-121.796826,36.777543],[-121.791544,36.815186],[-121.81273242676198,36.85004944374549],[-121.862266,36.931552],[-121.906468,36.96895],[-121.95167,36.97145],[-122.027174,36.95115],[-122.06731672905995,36.953595689731394],[-122.105976,36.955951],[-122.20618,37.013949],[-122.260481,37.072548],[-122.284882,37.101747],[-122.29431019191298,37.105141386717996],[-122.322971,37.11546],[-122.344029,37.144099],[-122.397065,37.187249],[-122.418452,37.248521],[-122.40559014390097,37.314965037743896],[-122.401323,37.337009],[-122.409258,37.374805],[-122.443687,37.435941],[-122.445987,37.461541],[-122.493789,37.492341],[-122.516689,37.52134],[-122.518088,37.576138],[-122.496786,37.612136],[-122.496784,37.686433],[-122.50067801908298,37.708132568017895],[-122.50560125134498,37.73556746524069],[-122.511983,37.77113],[-122.465396,37.800879],[-122.398139,37.80563],[-122.385323,37.790724],[-122.376462,37.738558],[-122.356784,37.729505],[-122.361749,37.71501],[-122.38982687658799,37.708331],[-122.39319,37.707531],[-122.360219,37.592501],[-122.244372,37.55814],[-122.168449,37.504143],[-122.12919970222397,37.52132199859079],[-122.111998,37.528851],[-122.144396,37.581866],[-122.152905,37.640771],[-122.16280251946198,37.667273013369694],[-122.163049,37.667933],[-122.213774,37.698695],[-122.24981,37.726406],[-122.252452,37.755129],[-122.312974,37.777244],[-122.333711,37.809797],[-122.303931,37.830087],[-122.32871428740698,37.89383234632079],[-122.33453,37.908791],[-122.378709,37.905191],[-122.425258,37.955672],[-122.367582,37.978168],[-122.368891,38.007948],[-122.34280385218798,38.00925387778169],[-122.321706,38.01031],[-122.262861,38.051473],[-122.26932005491696,38.060374497531186],[-122.301804,38.105142],[-122.393588,38.143449],[-122.397581230624,38.142003597253286],[-122.488499639259,38.10909447430819],[-122.491283,38.108087],[-122.499465,38.032165],[-122.452995,37.996167],[-122.488665,37.966714],[-122.486375,37.921881],[-122.448413,37.89341],[-122.41847,37.852721],[-122.483483,37.826728],[-122.537285,37.830328],[-122.60129,37.875126],[-122.678474,37.906604],[-122.70264,37.89382],[-122.754606,37.935527],[-122.797405,37.976657],[-122.856573,38.016717],[-122.939711,38.031908],[-122.97439,37.992429],[-123.011533,38.003438],[-122.960889,38.112962],[-122.953629,38.17567],[-122.987149,38.237538],[-122.986319,38.273164],[-123.00314647705598,38.29570523871448],[-123.004122,38.297012],[-123.053504,38.299385],[-123.068437,38.33521],[-123.085572,38.390525],[-123.166428,38.474947],[-123.249797,38.511045],[-123.331899,38.565542],[-123.349612,38.596805],[-123.441774,38.699744],[-123.514784,38.741966],[-123.54092201163398,38.76765621603928],[-123.571987,38.798189],[-123.638637,38.843865],[-123.659846,38.872529],[-123.71054,38.91323],[-123.732892,38.954994],[-123.69074,39.021293],[-123.721505,39.125327],[-123.765891,39.193657],[-123.798991,39.271355],[-123.825331,39.360814],[-123.81469,39.446538],[-123.766475,39.552803],[-123.782322,39.621486],[-123.792659,39.684122],[-123.829545,39.723071],[-123.851714,39.832041],[-123.907664,39.863028],[-123.954952,39.922373],[-124.02520517453,40.00129934166899],[-124.035904,40.013319],[-124.068908,40.021307],[-124.087086,40.078442],[-124.139952,40.11635],[-124.187874,40.130542],[-124.258405,40.184277],[-124.34307,40.243979],[-124.363414,40.260974],[-124.353124,40.331425],[-124.365357,40.374855],[-124.409591,40.438076],[-124.387023,40.504954]]]]}}, {"type":"Feature","properties":{"name":"District of Columbia","income":{"1995":33682,"1996":34436,"1997":34980,"1998":36442,"1999":38654,"2000":40606,"2001":41112,"2002":40617,"2003":43215,"2004":46211,"2005":48078,"2006":51746,"2007":54812,"2008":58553,"2009":58906,"2010":60729,"2011":62087,"2012":65231,"2013":66326,"2014":69992,"2015":73115}},"geometry":{"type":"Polygon","coordinates":[[[-77.119759,38.934343],[-77.041018,38.995548],[-77.00254624424699,38.96553170044589],[-76.909393,38.892852],[-76.979497,38.837812],[-77.039006,38.791645],[-77.03906635676466,38.841271889518595],[-77.039099,38.868112],[-77.0902,38.904211],[-77.119759,38.934343]]]}}, {"type":"Feature","properties":{"name":"Florida","income":{"1995":29998,"1996":31008,"1997":32877,"1998":34757,"1999":36309,"2000":38784,"2001":37319,"2002":38226,"2003":38985,"2004":40900,"2005":42437,"2006":45494,"2007":47804,"2008":47802,"2009":44755,"2010":44390,"2011":44250,"2012":45006,"2013":46021,"2014":47439,"2015":49416}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-81.811693,24.568745],[-81.751266,24.653517],[-81.672338,24.699514],[-81.584599,24.736696],[-81.571151,24.756354],[-81.44351,24.813364],[-81.305054,24.755185],[-81.243232,24.673998],[-81.342192,24.637774],[-81.401889,24.623544],[-81.443915,24.642677],[-81.517404,24.621239],[-81.595334,24.593107],[-81.685243,24.558676],[-81.812536,24.545469],[-81.811693,24.568745]]],[[[-82.01491,24.543071],[-81.983908,24.580682],[-81.868711,24.58412],[-81.918855,24.498131],[-82.028091,24.498716],[-82.01491,24.543071]]],[[[-82.188031,24.574699],[-82.144099,24.622481],[-82.086643,24.590071],[-82.100757,24.533288],[-82.179454,24.52947],[-82.188031,24.574699]]],[[[-87.592064,30.95146],[-87.598937,30.997422],[-87.59882894626209,30.99742217690529],[-87.519533,30.997552],[-87.425791,30.998058],[-87.312206,30.998404],[-87.16308069276556,30.99902418387759],[-87.162644,30.999026],[-86.927851,30.997678],[-86.831979,30.997354],[-86.78569197600586,30.99698299351679],[-86.68824096424608,30.99620189000149],[-86.563494,30.995202],[-86.38864466200037,30.994528215275192],[-86.364974,30.994437],[-86.18724804898129,30.994066723462193],[-86.03503810495057,30.993749607302295],[-85.893632,30.993455],[-85.749715,30.995282],[-85.57949757633826,30.99702874841089],[-85.49800158508948,30.99786504936139],[-85.48829828893909,30.99796462328729],[-85.333319,30.999555],[-85.145959,31.000693],[-85.031285,31.000647],[-85.002499,31.000682],[-85.006062,30.977039],[-84.983757,30.936984],[-84.935698,30.878703],[-84.934283,30.834033],[-84.91815,30.772082],[-84.864693,30.711542],[-84.86346384438247,30.711497014654395],[-84.812997,30.70965],[-84.474519,30.692783],[-84.38075418355248,30.688827197045892],[-84.28551450903947,30.684809171948],[-84.124993,30.678037],[-84.08375308229998,30.67594339796799],[-84.007454,30.67206996846919],[-83.820973,30.662603],[-83.743729,30.65852691375049],[-83.61170405882639,30.651560093708593],[-83.499951,30.645663],[-83.35771631362809,30.637137873134193],[-83.30934712159579,30.634238766671597],[-83.13661885820359,30.623885944893093],[-83.131431,30.623575],[-82.877311,30.609016],[-82.68952979847276,30.597889290641792],[-82.58400518641946,30.591636579087588],[-82.45979243541368,30.58427652830619],[-82.459581,30.584264],[-82.41898411217848,30.580916669731494],[-82.218607,30.564395],[-82.229427,30.520814],[-82.200965,30.474427],[-82.210318,30.424577],[-82.180043,30.36861],[-82.143306,30.363378],[-82.094709,30.360766],[-82.05098298168086,30.368367775944893],[-82.040766,30.370144],[-82.042011,30.403253],[-82.028232,30.447385],[-82.018381,30.531176],[-82.015728,30.601698],[-82.049529,30.655544],[-82.041834,30.692374],[-82.032667,30.750674],[-81.994992,30.786074],[-81.943187,30.827437],[-81.90597843940638,30.82140734150199],[-81.902354,30.82082],[-81.868624,30.792756],[-81.808543,30.790016],[-81.763384,30.773821],[-81.732238,30.749635],[-81.668283,30.744644],[-81.633273,30.729603],[-81.56171,30.715597],[-81.528281,30.723359],[-81.507218,30.722936],[-81.444124,30.709714],[-81.42742,30.69802],[-81.443099,30.600938],[-81.434064,30.522569],[-81.42895473764328,30.50618307416519],[-81.42601,30.496739],[-81.410809,30.482039],[-81.396407,30.34004],[-81.37437612802329,30.252931],[-81.288955,29.91518],[-81.270442,29.883106],[-81.26193346057477,29.82212348667609],[-81.256711,29.784693],[-81.21040959655379,29.67064080570429],[-81.163581,29.55529],[-81.10296735174536,29.426996650451994],[-81.046678,29.307856],[-80.966176,29.14796],[-80.907275,29.064262],[-80.787021,28.875266],[-80.72750567007368,28.791192871322696],[-80.647288,28.677875],[-80.583884,28.597705],[-80.525094,28.459454],[-80.587813,28.410856],[-80.606874,28.336484],[-80.604214,28.257733],[-80.589975,28.17799],[-80.547675,28.048795],[-80.44767694921757,27.860513513360996],[-80.383695,27.740045],[-80.330956,27.597541],[-80.31668661162037,27.557340024607594],[-80.253665,27.37979],[-80.19802135265869,27.263008803672495],[-80.153375,27.169308],[-80.138605,27.111517],[-80.116772,27.072397],[-80.0830776297553,26.970534],[-80.046263,26.859238],[-80.038962,26.813960752739895],[-80.033770917966,26.781768189419893],[-80.03212,26.77153],[-80.035763,26.676043],[-80.03556853593979,26.645076056888396],[-80.035363,26.612346],[-80.038863,26.569347],[-80.050363,26.509549],[-80.06159101082606,26.426527042783494],[-80.07587443944318,26.320912769880195],[-80.085565,26.249259],[-80.10865850558918,26.093293886255392],[-80.109566,26.087165],[-80.11297825128537,26.017023960833995],[-80.11501796449997,25.97509633226789],[-80.11512892389007,25.972815490010593],[-80.117904,25.915772],[-80.11451424410777,25.87419963469209],[-80.11438522427608,25.87261732028789],[-80.109953,25.81826],[-80.123806,25.762767],[-80.154972,25.66549],[-80.176916,25.685062],[-80.229107,25.732509],[-80.265879,25.658373],[-80.301464,25.613299],[-80.313918,25.539164],[-80.31597598143269,25.532620827266093],[-80.337049,25.465621],[-80.31036,25.389707],[-80.234849,25.42196],[-80.176024,25.521154],[-80.163156,25.452184],[-80.23239055893038,25.337069459412696],[-80.238555,25.32682],[-80.358183,25.153228],[-80.496761,24.999324],[-80.651189,24.866131],[-80.966245,24.707852],[-81.103373,24.669463],[-81.148718,24.710477],[-81.038908,24.772596],[-80.847471,24.851753],[-80.610869,25.006995],[-80.516571,25.095457],[-80.500513,25.156674],[-80.495394,25.199808],[-80.542391,25.206379],[-80.650532,25.189097],[-80.710607,25.15253],[-80.747746,25.147441],[-80.812133,25.186039],[-80.85817004003059,25.177520326526093],[-80.87546,25.174321],[-80.915924,25.141301],[-81.009598,25.125403],[-81.079859,25.118797],[-81.142278,25.183],[-81.170907,25.245857],[-81.148103,25.332793],[-81.146765,25.407577],[-81.208201,25.504937],[-81.240519,25.599041],[-81.289901,25.673554],[-81.355986,25.703526],[-81.38381,25.776751],[-81.44186477179917,25.803129028430995],[-81.472239,25.81693],[-81.614735,25.893977],[-81.64023695805679,25.877537579285093],[-81.672633,25.856654],[-81.727086,25.907207],[-81.757463,26.000374],[-81.808833,26.152246],[-81.844555,26.327712],[-81.84648524796168,26.330372048502795],[-81.923611,26.436658],[-81.956611,26.452358],[-82.013913,26.452058],[-82.075015,26.422059],[-82.126671,26.436279],[-82.180717,26.476257],[-82.245395,26.601094],[-82.264351,26.698496],[-82.264682,26.756836],[-82.28054127762877,26.78930858644309],[-82.314277,26.858384],[-82.36920139216907,26.946081025633497],[-82.452673,27.079359],[-82.51658542278818,27.20782630324179],[-82.539719,27.254326],[-82.610581,27.348817],[-82.64817061685946,27.38972],[-82.691821,27.437218],[-82.743017,27.531086],[-82.719852,27.528933],[-82.65072,27.523115],[-82.584629,27.596021],[-82.55288720706358,27.64544759636549],[-82.514265,27.705588],[-82.477638,27.723004],[-82.43198,27.768092],[-82.448786,27.810036],[-82.47344674878919,27.81758562552729],[-82.489849,27.822607],[-82.553946,27.848462],[-82.56638042463608,27.836338311914194],[-82.586519,27.816703],[-82.622723,27.779868],[-82.62502,27.732706],[-82.652521,27.700307],[-82.705017,27.62531],[-82.733076,27.612972],[-82.738467,27.678504],[-82.746223,27.731306],[-82.790224,27.791603],[-82.846526,27.854301],[-82.840882,27.937162],[-82.82835468921638,28.01887958165689],[-82.828163,28.02013],[-82.850881,28.102451],[-82.85938495603288,28.172175074604493],[-82.859624,28.174135],[-82.764103,28.244345],[-82.73146,28.325075],[-82.697433,28.420166],[-82.69079501337606,28.43334192576269],[-82.665055,28.484434],[-82.656694,28.544814],[-82.668149,28.622411],[-82.66871140214478,28.69430326858519],[-82.668722,28.695658],[-82.712373,28.720921],[-82.713121,28.800283],[-82.730245,28.850155],[-82.688864,28.905609],[-82.723861,28.953506],[-82.75557380869569,29.000930118260392],[-82.759378,29.006619],[-82.759704,29.054192],[-82.823659,29.098902],[-82.798876,29.114504],[-82.827073,29.158425],[-82.927107,29.168907],[-82.996144,29.178074],[-83.016248,29.125371],[-83.053207,29.130839],[-83.078986,29.196944],[-83.074734,29.247975],[-83.107477,29.268889],[-83.16592181158639,29.28909184264659],[-83.169576,29.290355],[-83.175518,29.34469],[-83.202446,29.394422],[-83.240509,29.433178],[-83.294747,29.437923],[-83.307828,29.468861],[-83.401552,29.523291],[-83.405068,29.59557],[-83.41412651315848,29.666065224482697],[-83.414701,29.670536],[-83.483567,29.698542],[-83.537645,29.72306],[-83.583045,29.787307],[-83.625026,29.856892],[-83.679219,29.918513],[-83.788729,29.976982],[-83.93151,30.039068],[-83.99231034047799,30.089268737728688],[-84.000716,30.096209],[-84.06299,30.101378],[-84.07613207191139,30.09908988373009],[-84.124889,30.090601],[-84.179149,30.073187],[-84.20801,30.084776],[-84.289727,30.057197],[-84.366115,30.008662],[-84.341439,29.962208],[-84.34114883318158,29.960756336105394],[-84.333746,29.923721],[-84.349066,29.896812],[-84.423834,29.902996],[-84.470323,29.924524],[-84.535873,29.910092],[-84.57744,29.887828],[-84.564976,29.81018],[-84.604003,29.786021],[-84.692619,29.763039],[-84.776954,29.692191],[-84.876731,29.655758],[-85.045074,29.586991],[-85.15731,29.64289],[-85.22842513307309,29.669559997761997],[-85.259719,29.681296],[-85.352615,29.659787],[-85.40283,29.758782],[-85.416548,29.842628],[-85.38473,29.920949],[-85.38924003323199,29.92411486260369],[-85.425956,29.949888],[-85.487764,29.961227],[-85.571907,30.02644],[-85.601178,30.056342],[-85.69681,30.09689],[-85.811219,30.17832],[-85.99610259397598,30.268901381209094],[-85.999937,30.27078],[-86.089963,30.303569],[-86.222561,30.343585],[-86.39737960650238,30.37749528041909],[-86.412076,30.380346],[-86.632953,30.396299],[-86.80035135196587,30.38450808737759],[-86.850625,30.380967],[-86.91920474980078,30.368991472122488],[-87.155392,30.327748],[-87.22976581136477,30.319632929800992],[-87.267827,30.31548],[-87.319518,30.317814],[-87.419859,30.297128],[-87.518324,30.280435],[-87.452282,30.344097],[-87.431784,30.403193],[-87.366601,30.436643],[-87.414685,30.457289],[-87.444722,30.507484],[-87.43145,30.550252],[-87.401189,30.604383],[-87.400189,30.657201],[-87.442291,30.692661],[-87.523621,30.738285],[-87.542268,30.767481],[-87.634943,30.865857],[-87.592064,30.95146]]]]}}, {"type":"Feature","properties":{"name":"Idaho","income":{"1995":32003,"1996":33279,"1997":33612,"1998":35863,"1999":36656,"2000":37929,"2001":38459,"2002":38242,"2003":39859,"2004":40509,"2005":41269,"2006":42846,"2007":46136,"2008":47561,"2009":44644,"2010":43259,"2011":43345,"2012":45296,"2013":46621,"2014":47572,"2015":48311}},"geometry":{"type":"Polygon","coordinates":[[[-117.243027,44.390974],[-117.215072,44.427162],[-117.225932,44.479389],[-117.167187,44.523431],[-117.14293,44.557236],[-117.094968,44.652011],[-117.062273,44.727143],[-117.013802,44.756841],[-116.9318,44.787181],[-116.88929518696699,44.84052977815328],[-116.865338,44.870599],[-116.833632,44.928976],[-116.858313,44.978761],[-116.841314,45.030907],[-116.78371,45.076972],[-116.78312826326696,45.07771250500999],[-116.754643,45.113972],[-116.696047,45.254679],[-116.69092662009098,45.26895523844489],[-116.674648,45.314342],[-116.588195,45.44292],[-116.502756,45.566608],[-116.463504,45.615785],[-116.528272,45.681473],[-116.535698,45.734231],[-116.593004,45.778541],[-116.665344,45.781998],[-116.736268,45.826179],[-116.78752,45.840204],[-116.79920453250098,45.851045435482895],[-116.859795,45.907264],[-116.886843,45.958617],[-116.915989,45.995413],[-116.942656,46.061],[-116.981962,46.084915],[-116.935473,46.142448],[-116.923958,46.17092],[-116.962966,46.19968],[-116.964379,46.253282],[-116.99726,46.303151],[-117.062748,46.353624],[-117.035545,46.410012],[-117.036645748421,46.426100482655386],[-117.039771,46.471779],[-117.03977765556199,46.541708992038096],[-117.03983338602796,47.12726899225409],[-117.039836,47.154734],[-117.04015975186299,47.259272],[-117.04049037556798,47.36602888669798],[-117.041634,47.7353],[-117.04130644645898,47.97745592002679],[-117.04121445346098,48.04546510380278],[-117.041107,48.124904],[-117.035289,48.422732],[-117.033671,48.656902],[-117.03293918211699,48.84666792120148],[-117.032351,48.999188],[-116.757234,48.999943],[-116.417503,49.000099],[-116.049193,49.000912],[-116.04915652064899,48.50204248175808],[-116.049155,48.481247],[-116.048948,48.309847],[-116.04892924777596,48.216127947927085],[-116.048911,48.12493],[-116.049153,47.999923],[-116.03856582987298,47.98463425644169],[-116.030751,47.973349],[-115.959946,47.898142],[-115.900934,47.843064],[-115.845474,47.814967],[-115.835365,47.760957],[-115.72377,47.696671],[-115.73627,47.654762],[-115.694284,47.62346],[-115.721207,47.576323],[-115.717024,47.532693],[-115.634684,47.48176],[-115.69293,47.457237],[-115.71034,47.417784],[-115.578619,47.367007],[-115.531971,47.314121],[-115.470959,47.284873],[-115.371825,47.265213],[-115.326903,47.255912],[-115.29211,47.209861],[-115.255786,47.174725],[-115.189451,47.131032],[-115.120917,47.061237],[-115.071254,47.022083],[-115.031651,46.971548],[-114.961422906068,46.932893875970784],[-114.927432,46.914185],[-114.943281,46.867971],[-114.880588,46.811791],[-114.79004,46.778729],[-114.76718,46.738828],[-114.699008,46.740223],[-114.67682716269498,46.73183873981309],[-114.626695,46.712889],[-114.621483,46.658143],[-114.59124789474797,46.65257477007719],[-114.547321,46.644485],[-114.453239,46.649266],[-114.360709,46.669059],[-114.33572493540497,46.65527296735359],[-114.320665,46.646963],[-114.331338,46.577781],[-114.351655,46.508119],[-114.403019,46.498675],[-114.384756,46.411784],[-114.422458,46.387097],[-114.431708,46.310744],[-114.441326,46.2738],[-114.449819,46.237119],[-114.445928,46.173933],[-114.514706,46.167726],[-114.5213,46.125287],[-114.460049,46.097104],[-114.480241,46.030325],[-114.441185,45.988453],[-114.402261,45.961489],[-114.413168,45.911479],[-114.388243,45.88234],[-114.422963,45.855381],[-114.517143,45.835993],[-114.562509,45.779927],[-114.504869,45.722176],[-114.499637,45.669035],[-114.53577,45.650613],[-114.538132,45.606834],[-114.52371067493497,45.58523308600019],[-114.506341,45.559216],[-114.456764,45.543983],[-114.36852,45.492716],[-114.279217,45.480616],[-114.251836,45.537812],[-114.18647,45.545539],[-114.083149,45.603996],[-114.014973,45.654008],[-114.015633,45.696127],[-113.971565,45.700636],[-113.94832148257,45.68257735844148],[-113.898883,45.644167],[-113.861404,45.62366],[-113.806729,45.602146],[-113.802849,45.523159],[-113.759986,45.480735],[-113.763368,45.427732],[-113.73239,45.385058],[-113.735601,45.325265],[-113.650064,45.23471],[-113.57467,45.128411],[-113.510819,45.099902],[-113.45197,45.059247],[-113.437726,45.006967],[-113.448958,44.953544],[-113.474573,44.910846],[-113.422376,44.842595],[-113.377153,44.834858],[-113.301508,44.798985],[-113.247166,44.82295],[-113.131387,44.764738],[-113.101154,44.708578],[-113.049349,44.62938],[-113.061071,44.577329],[-113.006828,44.518439],[-113.006846,44.471715],[-112.951146,44.416699],[-112.881769,44.380315],[-112.82682688126498,44.40520243176749],[-112.821896,44.407436],[-112.828191,44.442472],[-112.735084,44.499159],[-112.707815,44.503023],[-112.601863,44.491015],[-112.473207,44.480027],[-112.387389,44.448058],[-112.358917,44.528847],[-112.286187,44.568472],[-112.221698,44.543519],[-112.125101,44.528527],[-112.034133,44.537716],[-111.870504,44.564033],[-111.807914,44.511716],[-111.704218,44.560205],[-111.61710703430498,44.55712724841859],[-111.562814,44.555209],[-111.519126,44.582916],[-111.468833,44.679335],[-111.45694723249397,44.69564073783949],[-111.438793,44.720546],[-111.385005,44.755128],[-111.37713823673496,44.75119641396359],[-111.323669,44.724474],[-111.26875,44.668279],[-111.224161,44.623402],[-111.201459,44.575696],[-111.143557,44.535732],[-111.122654,44.493659],[-111.048974,44.474072],[-111.049148,44.374925],[-111.048452,44.114831],[-111.04721938441998,43.983452760701795],[-111.046515,43.908376],[-111.04611,43.687848],[-111.04536056096998,43.50105145111219],[-111.044617,43.31572],[-111.044143,43.072364],[-111.04405270511799,43.019407032899],[-111.043959,42.96445],[-111.043564,42.722624],[-111.04553029271298,42.513912877775084],[-111.04708,42.34942],[-111.046689,42.001567],[-111.374129,42.000893],[-111.471381,41.999739],[-111.50780619568698,41.999685678364294],[-111.50781303517599,41.99968566835219],[-111.750778,41.99933],[-112.10951205421198,41.99759809629469],[-112.109532,41.997598],[-112.15917745150998,41.99868192973779],[-112.264936,42.000991],[-112.648019,42.000307],[-113.00004013962398,41.99822761253908],[-113.000821,41.998223],[-113.249159,41.996203],[-113.496548,41.993305],[-113.817964,41.98858],[-114.041723,41.99372],[-114.28179946721997,41.99421388575789],[-114.281855,41.994214],[-114.598267,41.994511],[-114.89921,41.999909],[-115.03810975243397,41.99863411567649],[-115.313877,41.996103],[-115.625914,41.997415],[-115.870181,41.996766],[-116.332763,41.997283],[-116.625947,41.997379],[-117.018203216741,41.99983985036909],[-117.026197,41.99989],[-117.026551,42.378557],[-117.026253,42.807447],[-117.026652,43.025128],[-117.026889,43.596033],[-117.02566381044599,43.68029363595399],[-117.023577,43.823811],[-116.98554503848997,43.88118485281379],[-116.976024,43.895548],[-116.959871,43.982925],[-116.937342,44.029376],[-116.977351,44.085364],[-116.89785467711496,44.15266639539139],[-116.895931,44.154295],[-116.902752,44.179467],[-116.965498,44.194126],[-116.971958,44.235677],[-117.059352,44.237244],[-117.121037,44.277585],[-117.170342,44.25889],[-117.216974,44.288357],[-117.21199550695297,44.29645109593828],[-117.192203,44.32863],[-117.216911,44.360163],[-117.243027,44.390974]]]}}, {"type":"Feature","properties":{"name":"Illinois","income":{"1995":38078,"1996":39490,"1997":41179,"1998":43141,"1999":45214,"2000":46327,"2001":46991,"2002":44946,"2003":47367,"2004":47711,"2005":50270,"2006":52012,"2007":54141,"2008":56230,"2009":53974,"2010":52967,"2011":53271,"2012":55126,"2013":56212,"2014":57458,"2015":59590}},"geometry":{"type":"Polygon","coordinates":[[[-91.50616790862227,40.20064351279509],[-91.49695749033947,40.24870387637279],[-91.492891,40.269923],[-91.469656,40.322409],[-91.419422,40.378264],[-91.372921,40.399108],[-91.379907,40.45211],[-91.367876,40.510479],[-91.394475,40.534543],[-91.374252,40.58259],[-91.339719,40.613488],[-91.247851,40.63839],[-91.18698,40.637297],[-91.18546060870426,40.638111812623485],[-91.12082,40.672777],[-91.11822293839748,40.69953465081909],[-91.115735,40.725168],[-91.091703,40.779708],[-91.092993,40.821079],[-91.044653,40.868356],[-90.985462,40.912141],[-90.952233,40.954047],[-90.945324,41.019279],[-90.95189414268127,41.06987273586639],[-90.95226541648216,41.07273174967],[-90.957246,41.111085],[-90.997906,41.162564],[-91.041536,41.166138],[-91.081445,41.214429],[-91.114186,41.250029],[-91.07441549801959,41.33363156904068],[-91.07408762367406,41.33432080192049],[-91.071552,41.339651],[-91.065058,41.369101],[-91.027787,41.423603],[-90.966662,41.430051],[-90.924343,41.42286],[-90.867282,41.448215],[-90.786282,41.452888],[-90.701159,41.454743],[-90.618537,41.485032],[-90.571136,41.516332],[-90.513134,41.519533],[-90.461432,41.523533],[-90.41583,41.562933],[-90.364128,41.579633],[-90.339528,41.598633],[-90.336729,41.664532],[-90.314687,41.69483],[-90.31185685041618,41.72853289215359],[-90.310708,41.742214],[-90.248631,41.779805],[-90.24236824739717,41.78276872598458],[-90.180643,41.811979],[-90.181401,41.844647],[-90.165065,41.883777],[-90.15815303370947,41.92984322737608],[-90.156902,41.938181],[-90.140613,41.995999],[-90.15968245112268,42.03308725758588],[-90.163446,42.040407],[-90.161159,42.106372],[-90.207421,42.149109],[-90.26908,42.1745],[-90.31569651427148,42.19394643225139],[-90.338169,42.203321],[-90.400653,42.239293],[-90.430884,42.27823],[-90.417125,42.319943],[-90.44632,42.357041],[-90.48434567271626,42.38159777819188],[-90.517516,42.403019],[-90.565248,42.438742],[-90.590416,42.447493],[-90.646727,42.471904],[-90.642843,42.508481],[-90.437011,42.507147],[-90.42637696073606,42.50717773522369],[-90.22319,42.507765],[-89.927006876764,42.50579048577459],[-89.926484,42.505787],[-89.83759488632558,42.50491035279149],[-89.493216,42.501514],[-89.40141681104056,42.50044193107369],[-89.36579860766348,42.50002596695148],[-89.042898,42.496255],[-88.99256022681729,42.495854719899185],[-88.94038486037799,42.49543982747118],[-88.77649576073519,42.494136600467385],[-88.70738,42.493587],[-88.70737771540178,42.49358701476958],[-88.506912,42.494883],[-88.304692,42.49560817275149],[-88.2169,42.495923],[-88.19952900144847,42.49575601569028],[-87.89770179730027,42.49285460462939],[-87.800477,42.49192],[-87.80337,42.420621],[-87.820858,42.361584],[-87.834769,42.301522],[-87.833377771567,42.29777370515449],[-87.800066,42.208024],[-87.79858945123848,42.20600660116559],[-87.75932656523857,42.15236197897989],[-87.74168992918976,42.12826515946779],[-87.741662,42.128227],[-87.74135523340428,42.12795543477159],[-87.68927562032826,42.08185194039079],[-87.682359,42.075729],[-87.668982,42.029142],[-87.63436753388699,41.932910240325484],[-87.62498211348098,41.906817810703586],[-87.624052,41.904232],[-87.612291,41.893335],[-87.613556,41.88448],[-87.616293,41.870929],[-87.60945,41.845233],[-87.58837594251469,41.81103407616639],[-87.58707716617299,41.80892642541059],[-87.58160266073317,41.80004241269999],[-87.560646,41.766034],[-87.530745,41.748235],[-87.524141,41.72399],[-87.524044,41.708335],[-87.52494,41.529735],[-87.52540935334748,41.47028066606168],[-87.526768,41.298177],[-87.52676788622747,41.29805160247919],[-87.52664815808238,41.16608994451159],[-87.52652,41.024837],[-87.52646330599117,41.01035481796449],[-87.526014,40.895582],[-87.52613649042368,40.736885081422884],[-87.526292,40.535409],[-87.52687577325378,40.49122440969039],[-87.52706526339918,40.47688229246149],[-87.530054,40.250671],[-87.53102161242799,40.14803539674569],[-87.532308,40.011587],[-87.53245449388427,39.88299911878229],[-87.532703,39.664868],[-87.53238528279098,39.60730494422149],[-87.53166668197439,39.47711099274289],[-87.531624,39.469378],[-87.531646,39.347888],[-87.578331,39.340343],[-87.600397,39.312904],[-87.59474584540598,39.25938361648299],[-87.593486,39.247452],[-87.577029,39.211123],[-87.640435,39.166727],[-87.63829341374408,39.15749254720249],[-87.625379,39.101806],[-87.572588,39.057286],[-87.579117,39.001607],[-87.529496,38.971925],[-87.527645,38.907688],[-87.52871766369788,38.90594378628919],[-87.54737,38.875614],[-87.53525705080847,38.85249146496739],[-87.521681,38.826576],[-87.498948,38.757774],[-87.545538,38.677613],[-87.62012,38.639489],[-87.637752,38.588512],[-87.64835676307446,38.56662871605759],[-87.660732,38.541092],[-87.654166,38.511911],[-87.714047,38.47988],[-87.74104,38.435576],[-87.75110594512049,38.41884920845479],[-87.779996,38.370842],[-87.831972,38.307241],[-87.908542,38.268581],[-87.968968,38.237389],[-87.97020084080388,38.23027105838579],[-87.975819,38.197834],[-87.927468,38.151946],[-87.96221,38.100054],[-87.98877,38.055591],[-88.030884,38.030713],[-88.016311,37.961574],[-88.040861,37.891767],[-88.05946949270077,37.8666898040108],[-88.067364,37.856051],[-88.02803,37.799224],[-88.059588,37.742608],[-88.132341,37.697142],[-88.160062,37.654332],[-88.13216343827247,37.57451700082999],[-88.131622,37.572968],[-88.072242,37.528826],[-88.06625032009708,37.50413832734819],[-88.062294,37.487837],[-88.157061,37.466937],[-88.281667,37.452596],[-88.358436,37.40486],[-88.41590217877568,37.42122063771888],[-88.418594,37.421987],[-88.465861,37.400547],[-88.486947,37.339596],[-88.514661,37.290948],[-88.471753,37.220155],[-88.424776,37.149901],[-88.444605,37.098601],[-88.476127,37.068223],[-88.48380327697997,37.06808026989549],[-88.49039944632467,37.067957622947894],[-88.531576,37.067192],[-88.56104392947259,37.08399998095839],[-88.61144,37.112745],[-88.693983,37.141155],[-88.753068,37.154701],[-88.835051,37.196486],[-88.92800482949427,37.226389766253085],[-88.931745,37.227593],[-88.93351721474778,37.227511279914594],[-89.000968,37.224401],[-89.058036,37.188767],[-89.099047,37.140967],[-89.168087,37.074218],[-89.16662021201968,37.07211034379988],[-89.128899,37.017908],[-89.132915,36.982057],[-89.195039,36.989768],[-89.257608,37.015496],[-89.30743669117298,37.02875944962789],[-89.359456,37.042606],[-89.384175,37.103267],[-89.456105,37.18812],[-89.470525,37.253357],[-89.48288928464397,37.260950718414094],[-89.517032,37.28192],[-89.49516,37.324795],[-89.47367943454117,37.33485390219459],[-89.428185,37.356158],[-89.42594,37.407471],[-89.471201,37.466473],[-89.5124,37.52981],[-89.50179104949977,37.55889571932319],[-89.49774592603917,37.56998591392818],[-89.494051,37.580116],[-89.506563,37.62505],[-89.521948,37.696475],[-89.591289,37.723599],[-89.667993,37.759484],[-89.68722138085306,37.79640671843929],[-89.696559,37.814337],[-89.782035,37.855092],[-89.851048,37.90398],[-89.923185,37.870672],[-89.93309579091499,37.88009905825239],[-89.974221,37.919217],[-89.95491,37.966647],[-90.008353,37.970179],[-90.080959,38.015428],[-90.126006,38.05057],[-90.20572862588267,38.088233183108585],[-90.218708,38.094365],[-90.252484,38.127571],[-90.25274632397579,38.12777382622939],[-90.322353,38.181593],[-90.35116414506028,38.21954445709449],[-90.363926,38.236355],[-90.372519,38.323354],[-90.349743,38.377609],[-90.34291526673718,38.38442732002759],[-90.34024428170427,38.38709462263628],[-90.288815,38.438453],[-90.271314,38.496052],[-90.26097605928697,38.51852678740779],[-90.25529488766936,38.53087771182099],[-90.248913,38.544752],[-90.18451,38.611551],[-90.18111,38.65955],[-90.18152438153136,38.66037288531049],[-90.19521,38.68755],[-90.20991,38.72605],[-90.16659464001557,38.77245013930509],[-90.166409,38.772649],[-90.117707,38.805748],[-90.113327,38.849306],[-90.20728230118557,38.898732322839884],[-90.230336,38.91086],[-90.27658372202559,38.91933846721158],[-90.298711,38.923395],[-90.395816,38.960037],[-90.45096994089188,38.96139500332449],[-90.467784,38.961809],[-90.500117,38.910408],[-90.555693,38.870785],[-90.595354,38.87505],[-90.657254,38.92027],[-90.66158290687677,38.93470330775319],[-90.676397,38.984096],[-90.713629,39.053977],[-90.681086,39.10059],[-90.707902,39.15086],[-90.72328362341267,39.22410297005759],[-90.72996,39.255894],[-90.840106,39.340438],[-90.93534994636859,39.39951952890709],[-90.937419,39.400803],[-91.03827,39.448436],[-91.064305,39.494643],[-91.100307,39.538695],[-91.148275,39.545798],[-91.174232,39.591975],[-91.18287550081966,39.598233115795395],[-91.27614,39.665759],[-91.30576033496517,39.68621547007789],[-91.367753,39.729029],[-91.36461660332327,39.75871822632229],[-91.361571,39.787548],[-91.397853,39.821122],[-91.436051,39.84551],[-91.428956,39.907729],[-91.43684326859906,39.94524346367849],[-91.43709,39.946417],[-91.484064,40.019332],[-91.497663,40.078257],[-91.511956,40.170441],[-91.50616790862227,40.20064351279509]]]}}, {"type":"Feature","properties":{"name":"Iowa","income":{"1995":33436,"1996":33721,"1997":35427,"1998":38159,"1999":39537,"2000":40443,"2001":41216,"2002":41052,"2003":42278,"2004":42865,"2005":43610,"2006":44560,"2007":47324,"2008":49007,"2009":48065,"2010":48031,"2011":49545,"2012":50997,"2013":52286,"2014":53816,"2015":54843}},"geometry":{"type":"Polygon","coordinates":[[[-96.621875,42.779255],[-96.577937,42.827645],[-96.537851,42.878475],[-96.54047232919328,42.90859569795599],[-96.541689,42.922576],[-96.500308,42.959391],[-96.520246,42.977643],[-96.492693,43.005089],[-96.511605,43.039927],[-96.458201,43.067554],[-96.45209751605368,43.082552925194484],[-96.439335,43.113916],[-96.458854,43.143356],[-96.475571,43.221054],[-96.522084,43.22096],[-96.552963,43.247281],[-96.55902734270967,43.257555675617986],[-96.578823,43.291095],[-96.530392,43.300034],[-96.524289,43.347214],[-96.521572,43.38564],[-96.594254,43.434153],[-96.584603,43.46961],[-96.598928,43.500457],[-96.45326,43.50039],[-96.198484,43.500335],[-96.05316283450999,43.50018770815748],[-95.86094620157228,43.49999288490559],[-95.834421,43.499966],[-95.486803,43.500246],[-95.45443223866057,43.50032208525],[-95.38778759402187,43.50047872890739],[-95.214938,43.500885],[-94.91461348471358,43.50059587298608],[-94.874235,43.500557],[-94.85455506761066,43.50055341915219],[-94.44284998971817,43.50047850765469],[-94.390597,43.500469],[-94.24796744155518,43.50017547670759],[-93.97076155852818,43.499605003207385],[-93.97076,43.499605],[-93.64853303117357,43.49953548967509],[-93.576728,43.49952],[-93.49735132522038,43.49953072451169],[-93.228861,43.499567],[-93.04919200781647,43.49955748002459],[-93.02434790054187,43.49955616363],[-92.870277,43.499548],[-92.553161,43.5003],[-92.55312809051877,43.50030003631229],[-92.44894795143777,43.50041498856269],[-92.178863,43.500713],[-92.07980199312827,43.50070488517658],[-91.824848,43.500684],[-91.73021699783769,43.50068570094609],[-91.61083500055437,43.500687846779286],[-91.491042,43.50069],[-91.217706,43.50055],[-91.232276,43.450952],[-91.21066335777269,43.41944178290329],[-91.199408,43.403032],[-91.207367,43.373659],[-91.154806,43.334826],[-91.107237,43.313645],[-91.05791,43.253968],[-91.087456,43.221891],[-91.134173,43.174405],[-91.175253,43.134665],[-91.17493491391117,43.08026037184519],[-91.174692,43.038713],[-91.15908430594746,42.98747779132278],[-91.155519,42.975774],[-91.138,42.903772],[-91.09882,42.864421],[-91.070716,42.775502],[-91.017239,42.719566],[-90.941567,42.683844],[-90.89696202715838,42.674318056434295],[-90.852497,42.664822],[-90.743677,42.64556],[-90.700856,42.626445],[-90.672727,42.576599],[-90.642843,42.508481],[-90.646727,42.471904],[-90.590416,42.447493],[-90.565248,42.438742],[-90.517516,42.403019],[-90.48434567271626,42.38159777819188],[-90.44632,42.357041],[-90.417125,42.319943],[-90.430884,42.27823],[-90.400653,42.239293],[-90.338169,42.203321],[-90.31569651427148,42.19394643225139],[-90.26908,42.1745],[-90.207421,42.149109],[-90.161159,42.106372],[-90.163446,42.040407],[-90.15968245112268,42.03308725758588],[-90.140613,41.995999],[-90.156902,41.938181],[-90.15815303370947,41.92984322737608],[-90.165065,41.883777],[-90.181401,41.844647],[-90.180643,41.811979],[-90.24236824739717,41.78276872598458],[-90.248631,41.779805],[-90.310708,41.742214],[-90.31185685041618,41.72853289215359],[-90.314687,41.69483],[-90.336729,41.664532],[-90.339528,41.598633],[-90.364128,41.579633],[-90.41583,41.562933],[-90.461432,41.523533],[-90.513134,41.519533],[-90.571136,41.516332],[-90.618537,41.485032],[-90.701159,41.454743],[-90.786282,41.452888],[-90.867282,41.448215],[-90.924343,41.42286],[-90.966662,41.430051],[-91.027787,41.423603],[-91.065058,41.369101],[-91.071552,41.339651],[-91.07408762367406,41.33432080192049],[-91.07441549801959,41.33363156904068],[-91.114186,41.250029],[-91.081445,41.214429],[-91.041536,41.166138],[-90.997906,41.162564],[-90.957246,41.111085],[-90.95226541648216,41.07273174967],[-90.95189414268127,41.06987273586639],[-90.945324,41.019279],[-90.952233,40.954047],[-90.985462,40.912141],[-91.044653,40.868356],[-91.092993,40.821079],[-91.091703,40.779708],[-91.115735,40.725168],[-91.11822293839748,40.69953465081909],[-91.12082,40.672777],[-91.18546060870426,40.638111812623485],[-91.18698,40.637297],[-91.247851,40.63839],[-91.339719,40.613488],[-91.374252,40.58259],[-91.394475,40.534543],[-91.367876,40.510479],[-91.379907,40.45211],[-91.372921,40.399108],[-91.419422,40.378264],[-91.498093,40.401926],[-91.519134,40.432822],[-91.563844,40.460988],[-91.608347,40.50004],[-91.618999,40.539084],[-91.670993,40.550937],[-91.685381,40.578892],[-91.71665498768186,40.603740139295994],[-91.729115,40.61364],[-91.939292,40.60615],[-91.94311745968568,40.606060586354],[-92.17978,40.600529],[-92.35080418672638,40.59725727637609],[-92.453745,40.595288],[-92.63790329359948,40.59095654709789],[-92.686693,40.589809],[-92.71459726304498,40.589582833836296],[-92.941595,40.587743],[-93.09729120374978,40.58382347732509],[-93.135802,40.582854],[-93.345442,40.580514],[-93.37438625876378,40.580397032609184],[-93.55689667427168,40.57965948506049],[-93.597352,40.579496],[-93.77434420403027,40.577530453391084],[-93.84093,40.576791],[-94.015492,40.57407370700959],[-94.091085,40.572897],[-94.23224071020826,40.57201461212659],[-94.310724,40.571524],[-94.47120772712316,40.570959458356995],[-94.533878,40.570739],[-94.63202591769478,40.57175958739999],[-94.819978,40.573714],[-94.91489786736157,40.57492116911129],[-95.068921,40.57688],[-95.20226600083026,40.578375628995985],[-95.335588,40.579871],[-95.37392505339868,40.58033237794148],[-95.533182,40.582249],[-95.765645,40.585208],[-95.748626,40.603355],[-95.781909,40.653272],[-95.846034,40.682605],[-95.888697,40.736292],[-95.834156,40.783016],[-95.83424381671439,40.78378438704309],[-95.841309,40.845604],[-95.810709,40.886681],[-95.81872727856988,40.89794806640649],[-95.837774,40.924712],[-95.828329,40.972378],[-95.865878,41.017403],[-95.86478476408527,41.05284550461349],[-95.863839,41.083507],[-95.868688,41.124698],[-95.86189806820938,41.160302348212696],[-95.856788,41.187098],[-95.90969,41.184398],[-95.90990849125477,41.191282850827896],[-95.911391,41.237998],[-95.890152,41.278308],[-95.92569,41.322197],[-95.92879,41.370096],[-95.92733624232008,41.38998793745959],[-95.922529,41.455766],[-95.982962,41.469778],[-95.99402039301187,41.506890640941485],[-96.005079,41.544004],[-96.080493,41.528199],[-96.09182,41.561086],[-96.118105,41.613495],[-96.111483,41.668548],[-96.10793787174647,41.676508989762084],[-96.0876,41.72218],[-96.064537,41.793002],[-96.107911,41.840339],[-96.12682125346538,41.86609524770159],[-96.159098,41.910057],[-96.132537,41.974625],[-96.223611,42.022652],[-96.272877,42.047238],[-96.2689,42.11359],[-96.347752,42.166806],[-96.33721609470588,42.2148495068956],[-96.336323,42.218922],[-96.336003,42.264806],[-96.35195719249597,42.280894704543286],[-96.407998,42.337408],[-96.411808,42.410894],[-96.381307,42.461694],[-96.445508,42.49063],[-96.477454,42.509589],[-96.49297,42.517282],[-96.476952,42.556079],[-96.48002247897999,42.56132477656069],[-96.526766,42.641184],[-96.591602,42.688081],[-96.624704,42.725497],[-96.621875,42.779255]]]}}, {"type":"Feature","properties":{"name":"Kentucky","income":{"1995":28929,"1996":30630,"1997":31730,"1998":33955,"1999":33732,"2000":35150,"2001":35977,"2002":35875,"2003":36663,"2004":37046,"2005":37377,"2006":39318,"2007":40299,"2008":41489,"2009":40061,"2010":40089,"2011":41141,"2012":41717,"2013":43307,"2014":42914,"2015":45178}},"geometry":{"type":"Polygon","coordinates":[[[-89.544434,36.57451],[-89.479346,36.566253],[-89.407906,36.562345],[-89.378694,36.622292],[-89.327319777009,36.62394628877049],[-89.324658,36.624032],[-89.278935,36.577699],[-89.227319,36.569375],[-89.199136,36.625649],[-89.17564977234687,36.65131926255349],[-89.165488,36.662426],[-89.202511,36.716618],[-89.15699,36.755968],[-89.15598490907037,36.786292663371384],[-89.155891,36.789126],[-89.147674,36.847148],[-89.120472,36.891896],[-89.10313544832657,36.94476090032229],[-89.098843,36.95785],[-89.132915,36.982057],[-89.128899,37.017908],[-89.16662021201968,37.07211034379988],[-89.168087,37.074218],[-89.099047,37.140967],[-89.058036,37.188767],[-89.000968,37.224401],[-88.93351721474778,37.227511279914594],[-88.931745,37.227593],[-88.92800482949427,37.226389766253085],[-88.835051,37.196486],[-88.753068,37.154701],[-88.693983,37.141155],[-88.61144,37.112745],[-88.56104392947259,37.08399998095839],[-88.531576,37.067192],[-88.49039944632467,37.067957622947894],[-88.48380327697997,37.06808026989549],[-88.476127,37.068223],[-88.444605,37.098601],[-88.424776,37.149901],[-88.471753,37.220155],[-88.514661,37.290948],[-88.486947,37.339596],[-88.465861,37.400547],[-88.418594,37.421987],[-88.41590217877568,37.42122063771888],[-88.358436,37.40486],[-88.281667,37.452596],[-88.157061,37.466937],[-88.062294,37.487837],[-88.06625032009708,37.50413832734819],[-88.072242,37.528826],[-88.131622,37.572968],[-88.13216343827247,37.57451700082999],[-88.160062,37.654332],[-88.132341,37.697142],[-88.059588,37.742608],[-88.02803,37.799224],[-87.970262,37.781856],[-87.935861,37.789703],[-87.903804,37.817762],[-87.938128,37.870651],[-87.92539337830539,37.89959148487409],[-87.921744,37.907885],[-87.87254,37.920999],[-87.808013,37.875191],[-87.723635,37.892058],[-87.71321078529026,37.883088390366495],[-87.681633,37.855917],[-87.625851,37.851919],[-87.608479,37.898794],[-87.551277,37.925418],[-87.486347,37.920218],[-87.44863585760947,37.93387786821488],[-87.418585,37.944763],[-87.331765,37.908253],[-87.30405745244198,37.89343254912228],[-87.270387407739,37.87542282658999],[-87.25525,37.867326],[-87.180063,37.841375],[-87.137502,37.807264],[-87.105614,37.767631],[-87.057836,37.827457],[-87.043049,37.875049],[-87.010315,37.919668],[-86.97774142511018,37.92569920837269],[-86.927747,37.934956],[-86.875874,37.97077],[-86.81365994128528,37.99603449514159],[-86.810913,37.99715],[-86.779993,37.956522],[-86.722247,37.892648],[-86.658374,37.869376],[-86.64670305785909,37.864908975897784],[-86.615215,37.852857],[-86.599848,37.906754],[-86.509368,37.902887],[-86.525174,37.968228],[-86.521825,38.038327],[-86.48805246712828,38.04366530889968],[-86.471903,38.046218],[-86.434046,38.086763],[-86.43357436408806,38.087144387579485],[-86.387216,38.124632],[-86.35640726797098,38.13527783676579],[-86.321274,38.147418],[-86.278656,38.098509],[-86.206439,38.021876],[-86.095766,38.00893],[-86.033386,37.970382],[-85.99735165975429,37.99122560229909],[-85.976028,38.00356],[-85.95172964591549,38.01494012709058],[-85.922395,38.028679],[-85.905164,38.11107],[-85.89591178773559,38.17992692087039],[-85.894764,38.188469],[-85.839664,38.23977],[-85.816164,38.282969],[-85.79451090677007,38.27795473579529],[-85.750962,38.26787],[-85.683561,38.295469],[-85.646201,38.342916],[-85.6344441449773,38.37839944757479],[-85.621625,38.417089],[-85.587758,38.450495],[-85.498866,38.468242],[-85.474354,38.504074],[-85.433136,38.523914],[-85.43297226942606,38.52412339698789],[-85.4156,38.546341],[-85.43141607075218,38.58628561310889],[-85.43617,38.598292],[-85.438742,38.659319],[-85.448862,38.713368],[-85.400481,38.73598],[-85.340953,38.733893],[-85.33264073375139,38.73481675434769],[-85.275454,38.741172],[-85.238665,38.722494],[-85.20176062254856,38.69744079184628],[-85.187278,38.687609],[-85.146861,38.695427],[-85.071928,38.741567],[-85.02105214167419,38.758527324713896],[-84.962535,38.778035],[-84.856904,38.790224],[-84.812877,38.786087],[-84.803247,38.850723],[-84.79869982295229,38.85922739020669],[-84.786406,38.88222],[-84.830472,38.897256],[-84.86442851899166,38.91384364104939],[-84.877762,38.920357],[-84.832617,38.96146],[-84.849445,39.000923],[-84.87757023112478,39.031262844093995],[-84.897171,39.052407],[-84.860689,39.07814],[-84.820157,39.10548],[-84.750749,39.147358],[-84.714048,39.132659],[-84.677247,39.09826],[-84.62228392463076,39.07842004166409],[-84.607928,39.073238],[-84.550844,39.09936],[-84.50651873743688,39.10176640818799],[-84.49918784070238,39.10216440086548],[-84.493743,39.10246],[-84.480943,39.11676],[-84.462042,39.12176],[-84.445242,39.114461],[-84.432941,39.083961],[-84.40094,39.046362],[-84.326539,39.027463],[-84.32120722685679,39.020586352689385],[-84.297255,38.989694],[-84.288164,38.955789],[-84.232132,38.880483],[-84.23230504540348,38.874707896031694],[-84.233265,38.842671],[-84.22616263396347,38.829777141242],[-84.212904,38.805707],[-84.135088,38.789485],[-84.05264617321959,38.77161466753579],[-84.051642,38.771397],[-83.978814,38.787104],[-83.928454,38.774583],[-83.90437508610479,38.76728387526779],[-83.852085,38.751433],[-83.834015,38.716008],[-83.78362,38.695641],[-83.77216,38.65815],[-83.70586163558556,38.63803786506599],[-83.679484,38.630036],[-83.64691140412668,38.641851934545784],[-83.642994,38.643273],[-83.626922,38.679387],[-83.533339,38.702105],[-83.440404,38.669361],[-83.376302,38.661473],[-83.320531,38.622713],[-83.286514,38.599241],[-83.26429890195868,38.613112496887496],[-83.239515,38.628588],[-83.172647,38.620252],[-83.128973,38.640231],[-83.112372,38.671685],[-83.042338,38.708319],[-83.03033493123107,38.71686767665609],[-83.011816,38.730057],[-82.943147,38.74328],[-82.889193,38.756076],[-82.88228999360929,38.741619223269595],[-82.871192,38.718377],[-82.869592,38.678177],[-82.851314,38.604334],[-82.8115423846504,38.57236958956188],[-82.800112,38.563183],[-82.724846,38.5576],[-82.675724,38.515504],[-82.66411690751568,38.50771559025699],[-82.618474,38.477089],[-82.593673,38.421809],[-82.59596426449998,38.38088976171549],[-82.597979,38.344909],[-82.571877,38.315781],[-82.581796,38.248592],[-82.58469381412559,38.24051299336969],[-82.598864,38.201007],[-82.626182,38.134835],[-82.549407,38.063063],[-82.464987,37.976859],[-82.47942012322297,37.938562524698085],[-82.487556,37.916975],[-82.41869,37.872375],[-82.39846481625888,37.84305415046289],[-82.369973,37.801749],[-82.327356,37.762233],[-82.32067495717779,37.74596584345939],[-82.296118,37.686174],[-82.226111,37.653092],[-82.141555,37.595166],[-82.064418,37.544516],[-81.968297,37.537798],[-82.201745,37.375108],[-82.309415,37.300066],[-82.31478127133458,37.29599456011749],[-82.355343,37.26522],[-82.449164,37.243908],[-82.55363382627456,37.20145269844589],[-82.558178,37.199606],[-82.565275702797,37.19590110688309],[-82.726294,37.111852],[-82.722254,37.057948],[-82.750715,37.024107],[-82.815748,37.007196],[-82.869183,36.974182],[-82.865192,36.920923],[-82.88361015487978,36.897314788915786],[-82.895445,36.882145],[-83.012587,36.847289],[-83.07559,36.850589],[-83.114693,36.796088],[-83.136395,36.743088],[-83.236399,36.726887],[-83.386099,36.686589],[-83.436508,36.666185],[-83.46095464746378,36.66613103627329],[-83.527112,36.665985],[-83.614513,36.633983],[-83.675413,36.600814],[-83.690714,36.582581],[-83.894421,36.586481],[-83.93076078394387,36.58769425811239],[-83.98761095068278,36.58959228607249],[-83.987842,36.5896],[-84.22719396199828,36.59217951235509],[-84.227332,36.592181],[-84.26132120150467,36.592741697266995],[-84.499938,36.596678],[-84.77845586435048,36.60321051221589],[-84.785341,36.603372],[-84.78539997855027,36.603375419935595],[-84.943948,36.612569],[-84.97486843583738,36.61458335931719],[-85.096128,36.622483],[-85.27628794749938,36.62615754080338],[-85.290627,36.62645],[-85.29581248572748,36.62614955936749],[-85.43640427288588,36.618003845027],[-85.488353,36.614994],[-85.731862,36.620429],[-85.78855654361386,36.62171185903469],[-85.873857,36.623642],[-85.97571317414399,36.62863771868169],[-86.081944,36.633848],[-86.20556526985598,36.63924687032879],[-86.41149619896639,36.6482404228482],[-86.507771,36.652445],[-86.551292,36.637985],[-86.56206765186529,36.640746673907294],[-86.606394,36.652107],[-86.76329096410846,36.64872067450179],[-86.813037,36.647647],[-87.06082634439286,36.64477088485159],[-87.1150035566884,36.64414204465119],[-87.33597905008078,36.64157716049309],[-87.347796,36.64144],[-87.64114589700208,36.63803604761009],[-87.64115,36.638036],[-87.69418590786428,36.63683824394369],[-87.853204,36.633247],[-87.849567,36.663701],[-88.011792,36.677025],[-88.070532,36.678118],[-88.055738,36.630475],[-88.033802,36.551733],[-88.050466,36.500053],[-88.05335080077587,36.49999625068159],[-88.127378,36.49854],[-88.48907673871317,36.501283719075694],[-88.51192,36.501457],[-88.51635805997938,36.50146419816328],[-88.81676415734808,36.50195143181319],[-88.82717803634047,36.50196832225689],[-88.83458902287427,36.50198034225929],[-88.964471,36.502191],[-89.211409,36.50563],[-89.34519431953878,36.50134320863689],[-89.417293,36.499033],[-89.539232,36.497934],[-89.571481,36.538087],[-89.544434,36.57451]]]}}, {"type":"Feature","properties":{"name":"Louisiana","income":{"1995":27265,"1996":28921,"1997":30466,"1998":30894,"1999":31904,"2000":32124,"2001":32959,"2002":33536,"2003":33792,"2004":35216,"2005":36547,"2006":39122,"2007":40866,"2008":43635,"2009":42460,"2010":42510,"2011":41804,"2012":42998,"2013":44234,"2014":44680,"2015":45829}},"geometry":{"type":"Polygon","coordinates":[[[-94.04305152761756,32.69302997666559],[-94.043026,32.797476],[-94.04300262156329,32.88108897892399],[-94.042964,33.019219],[-93.81455301343377,33.01938904487079],[-93.80490777463038,33.01939622545089],[-93.723273,33.019457],[-93.52099355377158,33.018742293588],[-93.49051240012037,33.01863459566629],[-93.377134,33.018234],[-93.23860696239936,33.01801587995659],[-93.197402,33.017951],[-92.988707610715,33.01725094015219],[-92.971137,33.017192],[-92.72474317317926,33.01434176767479],[-92.723553,33.014328],[-92.501383,33.01216],[-92.222825,33.00908],[-92.06914659248126,33.00848243025689],[-92.06910375856128,33.008482263699584],[-91.875128,33.007728],[-91.489176,33.006182],[-91.4603917718319,33.00599705570149],[-91.43593108033177,33.0058398909721],[-91.26456405022049,33.00473882427039],[-91.166073,33.004106],[-91.134414,32.980533],[-91.072075,32.937832],[-91.070602,32.888659],[-91.13789,32.848975],[-91.161669,32.812465],[-91.157614,32.776033],[-91.113652,32.73997],[-91.056999,32.72558],[-91.098762,32.685291],[-91.079506,32.60068],[-91.05529310494987,32.5789835010771],[-91.049312,32.573624],[-91.04876042776367,32.57279704042139],[-91.011275,32.516596],[-91.060516,32.512361],[-91.052907,32.438442],[-90.965986,32.424806],[-90.986672,32.35176],[-90.92117,32.342073],[-90.947834,32.283486],[-90.991227,32.214662],[-91.108509,32.20815],[-91.03947231890697,32.10796814266529],[-91.034707,32.101053],[-91.079108,32.050255],[-91.080808,32.023456],[-91.117409,31.987057],[-91.17741,31.973257],[-91.18111,31.920059],[-91.234899,31.876863],[-91.24401516132468,31.86973243750389],[-91.290135,31.833658],[-91.345714,31.842861],[-91.359514,31.799362],[-91.32045873328158,31.74780061448219],[-91.318576,31.745315],[-91.38012452998348,31.732626953049998],[-91.380915,31.732464],[-91.395715,31.644165],[-91.463817,31.620365],[-91.457517,31.587566],[-91.437616,31.546166],[-91.489618,31.534266],[-91.51714,31.498394],[-91.510356,31.438928],[-91.532336,31.390275],[-91.536061,31.338355],[-91.508858,31.291644],[-91.564192,31.261633],[-91.621358,31.267811],[-91.644356,31.234414],[-91.590051,31.193693],[-91.59099389306448,31.191998565698793],[-91.621671,31.13687],[-91.594693,31.091444],[-91.560365,31.049508],[-91.62825729820878,31.00509700189519],[-91.636942,30.999416],[-91.224068,30.999183],[-91.17614012396687,30.99922420231859],[-91.06012746799657,30.99932393530919],[-90.82582914129189,30.99952535534059],[-90.758775,30.999583],[-90.56719540065848,30.99994502439989],[-90.54757442523307,30.999982101791588],[-90.34724108066209,31.00036066798079],[-90.346007,31.000363],[-90.25955494049128,31.00066178122909],[-89.897516,31.001913],[-89.83590782432817,31.002101423117598],[-89.728147,31.002431],[-89.72817569016057,31.00231388798409],[-89.750073,30.91293],[-89.791745,30.820387],[-89.836331,30.727197],[-89.82618035911518,30.668823270185197],[-89.821868,30.644024],[-89.791664,30.551524],[-89.712493,30.47751],[-89.69993208284077,30.454036880785996],[-89.678514,30.414012],[-89.634208,30.308256],[-89.607655,30.217096],[-89.524504,30.180753],[-89.60508845655457,30.142814157559293],[-89.656986,30.118381],[-89.683712,30.076018],[-89.782534,30.045372],[-89.845065,30.01841],[-89.84529711957238,30.016381840570094],[-89.852583,29.952721],[-89.795969,29.934003],[-89.744272,29.917647],[-89.701725,29.874085],[-89.647064,29.863602],[-89.598129,29.881409],[-89.574425,29.983738],[-89.494064,30.040972],[-89.444618,30.060959],[-89.342163,30.059172],[-89.303026,30.09157],[-89.233168,30.134957],[-89.183256,30.149344],[-89.185799,30.063934],[-89.215675,29.993523],[-89.231178,29.925484],[-89.236298,29.877081],[-89.293251,29.803053],[-89.271034,29.756355],[-89.399162,29.770592],[-89.403956,29.681808],[-89.465562,29.651738],[-89.50096675313368,29.63345542505879],[-89.504738,29.631508],[-89.535202,29.648567],[-89.602109,29.610295],[-89.564615,29.543786],[-89.569607,29.494044],[-89.53215,29.434567],[-89.482318,29.406222],[-89.380001,29.391785],[-89.312085,29.388038],[-89.257852,29.336872],[-89.200389,29.344418],[-89.134337,29.27934],[-89.116653,29.219532],[-89.025974,29.215153],[-89.01428,29.166913],[-89.066617,29.090714],[-89.11653,29.074097],[-89.148792,29.02967],[-89.142866,28.991623],[-89.218673,29.022515],[-89.259354,29.058358],[-89.322011,29.010251],[-89.400966,28.933812],[-89.40353,29.016964],[-89.361098,29.071848],[-89.390515,29.123576],[-89.432932,29.149023],[-89.482844,29.215053],[-89.564551,29.242527],[-89.606651,29.252023],[-89.639663,29.290531],[-89.726162,29.304026],[-89.842641,29.318823],[-89.883463,29.307103],[-89.90270632402427,29.293036606495995],[-89.95646,29.253744],[-90.058512,29.183687],[-90.08983544819417,29.164475356621097],[-90.122753,29.144286],[-90.223587,29.085075],[-90.334935,29.063803],[-90.40947090171977,29.05844438592819],[-90.442734,29.056053],[-90.488117,29.05876],[-90.652116,29.057721],[-90.748377,29.04006],[-90.81255,29.042138],[-90.867853,29.056064],[-90.877583,29.104891],[-90.941877,29.162373],[-91.000096,29.169481],[-91.094015,29.187711],[-91.158148,29.2181],[-91.278792,29.247776],[-91.334885,29.298775],[-91.276647,29.329825],[-91.265452,29.360976],[-91.26632267071919,29.361363733345996],[-91.334051,29.391525],[-91.363967,29.420664],[-91.347514,29.444438],[-91.394307,29.497115],[-91.460963,29.469961],[-91.48559,29.499116],[-91.531021,29.531543],[-91.537445,29.565888],[-91.541974,29.594353],[-91.600179,29.631156],[-91.643832,29.630625],[-91.623829,29.69924],[-91.667128,29.745822],[-91.737253,29.74937],[-91.808142,29.725097],[-91.85307,29.702936],[-91.86255699652258,29.667395463759892],[-91.873266,29.627277],[-91.80373,29.595952],[-91.711081,29.569328],[-91.768263,29.490362],[-91.821579,29.473925],[-91.915321,29.518513],[-92.030186,29.572669],[-92.04289430382738,29.577480288971994],[-92.064513,29.585665],[-92.158624,29.581616],[-92.25186,29.539354],[-92.323465,29.531497],[-92.40986,29.547477],[-92.473585,29.561081],[-92.568038,29.577397],[-92.61723443744988,29.589059016173493],[-92.684486,29.605001],[-92.879992,29.680285],[-92.993128,29.723846],[-93.088182,29.749125],[-93.17693,29.770487],[-93.295573,29.775071],[-93.411087,29.767357],[-93.538462,29.763299],[-93.741948,29.736343],[-93.79925,29.71526],[-93.837971,29.690619],[-93.863204,29.724059],[-93.890821,29.761673],[-93.929208,29.802952],[-93.872446,29.85165],[-93.85230987092228,29.87209100439189],[-93.830374,29.894359],[-93.807815,29.954549],[-93.741078,30.021571],[-93.70633576247016,30.05218024153089],[-93.70394,30.054291],[-93.702436,30.112721],[-93.703764,30.173936],[-93.713359,30.225261],[-93.71106217130087,30.24397071564029],[-93.70719,30.275513],[-93.760328,30.329924],[-93.745333,30.397022],[-93.738540238226,30.40226367248079],[-93.702665,30.429947],[-93.710117,30.5064],[-93.729195,30.544842],[-93.684329,30.592586],[-93.685121,30.625201],[-93.629904,30.67994],[-93.617688,30.738479],[-93.569303,30.802969],[-93.558617,30.869424],[-93.55457585434549,30.87746950186109],[-93.530936,30.924534],[-93.549841,30.967118],[-93.539526,31.008498],[-93.531219,31.051678],[-93.540278,31.128868],[-93.535097,31.185614],[-93.55249730750228,31.18482002344679],[-93.60060308736288,31.18262495526879],[-93.602443,31.182541],[-93.613942,31.259375],[-93.67544,31.30104],[-93.668146,31.375103],[-93.697603,31.428409],[-93.749476,31.46869],[-93.725925,31.504092],[-93.787687,31.527344],[-93.83492321447775,31.586210021077996],[-93.834924,31.586211],[-93.816838,31.622509],[-93.803419,31.700686],[-93.85339,31.805467],[-93.87825189538658,31.844276557245585],[-93.909557,31.893144],[-93.977461,31.926419],[-94.02942840659598,31.979686964167996],[-94.041833,31.992402],[-94.042681,32.137956],[-94.04269592374007,32.196004974824895],[-94.042739,32.363559],[-94.0427882328053,32.392283193281195],[-94.043083,32.564261],[-94.04305152761756,32.69302997666559]]]}}, {"type":"Feature","properties":{"name":"Maryland","income":{"1995":42132,"1996":44196,"1997":45289,"1998":47492,"1999":49781,"2000":52740,"2001":53090,"2002":53866,"2003":54302,"2004":57019,"2005":61546,"2006":65041,"2007":67989,"2008":70482,"2009":69193,"2010":68933,"2011":70075,"2012":71169,"2013":72482,"2014":73851,"2015":75784}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-76.046213,38.025533],[-76.007337,38.036706],[-75.980089,38.004891],[-75.984648,37.938121],[-76.04653,37.953586],[-76.046213,38.025533]]],[[[-79.484372,39.3443],[-79.482366,39.531689],[-79.476662,39.721078],[-79.39245840502238,39.72143935864009],[-79.045576,39.722928],[-78.93117513430978,39.72299692517329],[-78.80829952962156,39.72307095627689],[-78.723578,39.723122],[-78.38047706456398,39.72270413883999],[-78.34283351857438,39.72265829292649],[-78.342593,39.722658],[-78.09897069616667,39.72246619442808],[-78.075861,39.722448],[-77.768644,39.721538],[-77.469274,39.720229],[-77.46914500368037,39.720229002249994],[-77.45943341952388,39.72022917164499],[-77.23995,39.720233],[-77.21702375523738,39.72021724838539],[-76.99931802633319,39.72006767235259],[-76.991062,39.720062],[-76.78709719975758,39.72104814611128],[-76.715771,39.721393],[-76.56947511721158,39.72145855910529],[-76.41898,39.721526],[-76.23968374111459,39.72164198992459],[-76.233485,39.721646],[-76.23327934711658,39.72164625562789],[-76.13569742699018,39.721767550606685],[-75.81207998484679,39.72216980924989],[-75.788596,39.722199],[-75.76690460670918,39.37765159355119],[-75.766895,39.377499],[-75.76044141645049,39.29678962110009],[-75.75643521556849,39.2466875371253],[-75.74815481425408,39.14313173095969],[-75.72310269333266,38.82982655652769],[-75.70755502642899,38.635385355059896],[-75.707551,38.635335],[-75.70177751524498,38.560766929078596],[-75.700382,38.542743],[-75.693721,38.460128],[-75.479283,38.453698],[-75.34128732034819,38.45243652595549],[-75.185455,38.451012],[-75.048939,38.451263],[-75.085518,38.32427],[-75.102947,38.311525],[-75.143229,38.220475],[-75.177394,38.130014],[-75.193796,38.096013],[-75.242266,38.027209],[-75.624341,37.994211],[-75.669711,37.950796],[-75.722662,37.97131],[-75.783815,37.972594],[-75.860727,37.91831],[-75.892686,37.916848],[-75.898956,37.974514],[-75.857507,38.038778],[-75.858881,38.060135],[-75.86381,38.100968],[-75.937089,38.124209],[-75.942375,38.187066],[-75.864104,38.200858],[-75.87544731146468,38.219709301961],[-75.888513,38.241423],[-75.92376608242829,38.246285277001995],[-75.9445,38.249145],[-76.038935,38.254932],[-76.031988,38.18742],[-76.011916,38.122214],[-76.005904,38.07717],[-76.048692,38.086728],[-76.095548,38.125123],[-76.088639,38.192649],[-76.135513,38.232185],[-76.217613,38.305683],[-76.257667,38.324855],[-76.25,38.362304],[-76.280551,38.403143],[-76.33636,38.492235],[-76.277461,38.541851],[-76.290043,38.569158],[-76.279589,38.60952],[-76.231187,38.61401],[-76.203065,38.610741],[-76.165435,38.6102],[-76.17016187458728,38.640842047150095],[-76.175159,38.673236],[-76.200334,38.670774],[-76.238725,38.712845],[-76.275015,38.712714],[-76.322418,38.679304],[-76.347998,38.686234],[-76.340543,38.730338],[-76.39035,38.757004],[-76.379739,38.788314],[-76.310081,38.796846],[-76.271575,38.851771],[-76.219328,38.812371],[-76.19109,38.82966],[-76.19686875994799,38.855741963420684],[-76.205063,38.892726],[-76.203638,38.928382],[-76.250868,38.92825],[-76.317947,38.911312],[-76.334019,38.860238],[-76.376202,38.850461],[-76.361727,38.939175],[-76.322296,39.006375],[-76.301847,39.039651],[-76.26503664040868,39.02855095534879],[-76.231765,39.018518],[-76.233457,39.091385],[-76.246481,39.119588],[-76.278527,39.145764],[-76.243166,39.213362],[-76.211253,39.269812],[-76.177704,39.298701],[-76.159673,39.335909],[-76.110527,39.372257],[-76.06149882195567,39.387748114115084],[-76.040962,39.394237],[-76.00688,39.414527],[-76.012312,39.453115],[-76.03764628831578,39.452642382309286],[-76.060931,39.452208],[-76.146373,39.40531],[-76.224161,39.35278],[-76.296609,39.301137],[-76.32541834195688,39.272905086082694],[-76.349994,39.248822],[-76.395509,39.231702],[-76.425281,39.205708],[-76.463483,39.205908],[-76.498384,39.204808],[-76.50400859091808,39.19928624912599],[-76.525785,39.177908],[-76.428681,39.131709],[-76.42186,39.081442],[-76.420394,39.04207],[-76.39408,39.011311],[-76.448981,38.982811],[-76.471281,38.956512],[-76.45028,38.941113],[-76.46938,38.907613],[-76.47397616365546,38.90269337862989],[-76.49068,38.884814],[-76.516944,38.851157],[-76.489878,38.838715],[-76.526979,38.787016],[-76.558743,38.756352],[-76.526655,38.72443],[-76.52709254739416,38.712750301238295],[-76.528923,38.663889],[-76.511278,38.615745],[-76.517506,38.539149],[-76.492699,38.482849],[-76.450937,38.442422],[-76.393378,38.389477],[-76.387002,38.361267],[-76.40019462469799,38.319871943961395],[-76.402894,38.311402],[-76.374481,38.296348],[-76.392668,38.239663],[-76.353516,38.178135],[-76.320136,38.138339],[-76.330794,38.099331],[-76.322093,38.036503],[-76.37179,38.079565],[-76.430425,38.119383],[-76.481036,38.115873],[-76.54038,38.152991],[-76.590637,38.214212],[-76.673462,38.234401],[-76.740055,38.235227],[-76.805949,38.252275],[-76.82703612928188,38.25830010061409],[-76.864292,38.268945],[-76.922177,38.311339],[-76.975492,38.347327],[-77.001638,38.421952],[-77.016371,38.445572],[-77.075489,38.42471],[-77.123325,38.410646],[-77.211188,38.380662],[-77.259962,38.435821],[-77.246584,38.538341],[-77.183767,38.600699],[-77.129084,38.614364],[-77.1302,38.635017],[-77.132501,38.673816],[-77.08578476515638,38.70528128183239],[-77.079499,38.709515],[-77.053199,38.709915],[-77.040998,38.737914],[-77.04067257077807,38.74669193048289],[-77.03923988508228,38.78533632562359],[-77.039006,38.791645],[-76.979497,38.837812],[-76.909393,38.892852],[-77.00254624424699,38.96553170044589],[-77.041018,38.995548],[-77.119759,38.934343],[-77.146601,38.96421],[-77.202502,38.96791],[-77.249803,38.985909],[-77.24840370497539,39.02688835429229],[-77.248403,39.026909],[-77.310705,39.052008],[-77.33003770595407,39.055952113490996],[-77.359702,39.062004],[-77.462617,39.076248],[-77.481279,39.105658],[-77.519929,39.120925],[-77.521222,39.161057],[-77.485971,39.185665],[-77.459883,39.218682],[-77.46006562649778,39.218842943859386],[-77.496606,39.251045],[-77.553114,39.279268],[-77.588235,39.301955],[-77.66613,39.317008],[-77.67769576207868,39.317940817087994],[-77.719519,39.321314],[-77.74593,39.353221],[-77.740012,39.401694],[-77.798201,39.475719],[-77.81094389626217,39.50073916656648],[-77.823762,39.525907],[-77.829814,39.587288],[-77.925988,39.607642],[-78.006734,39.601337],[-78.02762910017326,39.620655962344095],[-78.08226,39.671166],[-78.225075,39.658878],[-78.313033,39.631001],[-78.33278802149908,39.62852759649879],[-78.382959,39.622246],[-78.438179,39.563524],[-78.460951,39.525987],[-78.46826959500288,39.526224270471694],[-78.590654,39.530192],[-78.65503617154668,39.54438224108369],[-78.707098,39.555857],[-78.73905,39.609697],[-78.77114,39.638387],[-78.851016,39.554044],[-78.942618,39.479614],[-78.956751,39.440264],[-79.035623,39.473344],[-79.06782557347339,39.47280233821589],[-79.091329,39.472407],[-79.166497,39.400888],[-79.26239211717608,39.32624382846739],[-79.283723,39.30964],[-79.35375,39.278039],[-79.424413,39.228171],[-79.486873,39.205961],[-79.484372,39.3443]]]]}}, {"type":"Feature","properties":{"name":"Michigan","income":{"1995":35940,"1996":38266,"1997":38883,"1998":41963,"1999":44221,"2000":45202,"2001":45688,"2002":44315,"2003":46291,"2004":44409,"2005":46072,"2006":47187,"2007":47931,"2008":48606,"2009":45254,"2010":45354,"2011":45931,"2012":46793,"2013":48200,"2014":49755,"2015":51063}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-84.61622,45.89447],[-84.517895,45.828543],[-84.419696,45.799823],[-84.35602,45.771895],[-84.394038,45.727623],[-84.484128,45.73071],[-84.587572,45.8067],[-84.650783,45.85921],[-84.61622,45.89447]]],[[[-85.701809,45.736129],[-85.651866,45.743139],[-85.524448,45.829794],[-85.360952,45.817554],[-85.377132,45.769013],[-85.509276,45.596475],[-85.561634,45.572213],[-85.622741,45.586028],[-85.696872,45.69725],[-85.701809,45.736129]]],[[[-86.138095,45.043038],[-86.04443,45.159582],[-85.989412,45.151069],[-85.954021,45.119281],[-85.976883,45.06266],[-86.081487,44.990096],[-86.154824,45.002394],[-86.138095,45.043038]]],[[[-86.693267,41.835403],[-86.597899,41.918291],[-86.501322,42.08454],[-86.466262,42.134406],[-86.36637912703829,42.243107727180885],[-86.356218,42.254166],[-86.284448,42.394563],[-86.27699404453148,42.41931031592629],[-86.240642,42.54],[-86.22869480100228,42.629511854701185],[-86.226638,42.644922],[-86.208309,42.762789],[-86.20853850290966,42.76754387191569],[-86.214138,42.883555],[-86.226305,42.988284],[-86.254646,43.083409],[-86.27392827867138,43.11836796870779],[-86.316259,43.195114],[-86.407832,43.338436],[-86.448743,43.432013],[-86.46351688668106,43.47232969950669],[-86.479276,43.515335],[-86.529507,43.593462],[-86.540787,43.644593],[-86.510319,43.698625],[-86.445123,43.771564],[-86.43548503825829,43.819429198004194],[-86.431198,43.84072],[-86.447915,43.918089],[-86.463136,43.970976],[-86.46320311524846,43.97106455971969],[-86.501738,44.021912],[-86.514702,44.058119],[-86.45806527573767,44.09928779829528],[-86.429871,44.119782],[-86.39139914690867,44.173701998925],[-86.38784339752875,44.178685538508894],[-86.351638,44.229429],[-86.26871,44.345324],[-86.251926,44.400984],[-86.248914,44.483004],[-86.23702086501648,44.51829858614469],[-86.220697,44.566742],[-86.25395,44.64808],[-86.248474,44.699046],[-86.160268,44.728189],[-86.089186,44.741496],[-86.07847345281048,44.77841599575308],[-86.065966,44.821522],[-86.058862,44.911012],[-85.980219,44.906136],[-85.9316,44.968788],[-85.854304,44.938147],[-85.780439,44.977932],[-85.746444,45.051229],[-85.681096,45.092693],[-85.633124,45.170899],[-85.551072,45.210742],[-85.531461,45.177247],[-85.56613,45.043633],[-85.55514270270878,45.02703454413689],[-85.520034,44.973996],[-85.475204,44.991053],[-85.4314154750083,45.016649452717694],[-85.380659,45.046319],[-85.366749,45.101591],[-85.380464,45.180876],[-85.37782997459678,45.207586816956386],[-85.371593,45.270834],[-85.294848,45.316408],[-85.196704,45.360641],[-85.09605687227098,45.36308804043479],[-85.054805,45.364091],[-84.959119,45.375973],[-84.912956,45.409776],[-84.980953,45.429382],[-85.040936,45.436701],[-85.109252,45.521626],[-85.119737,45.569026],[-85.061488,45.639505],[-84.97095,45.686334],[-85.014509,45.760329],[-84.866976,45.752066],[-84.772765,45.789301],[-84.732242,45.780496853288994],[-84.718904,45.777599],[-84.553311,45.698566],[-84.46168,45.652404],[-84.413642,45.669427],[-84.329537,45.66438],[-84.21089334555627,45.62623101784838],[-84.196043,45.621456],[-84.126532,45.556616],[-84.095905,45.497298],[-83.99835,45.491158],[-83.909472,45.485784],[-83.841543,45.435287],[-83.697316,45.396239],[-83.599273,45.352561],[-83.488826,45.355872],[-83.385104,45.274195],[-83.405914,45.227157],[-83.38521107925648,45.20710399314799],[-83.315924,45.139992],[-83.265896,45.026844],[-83.340257,45.041545],[-83.399255,45.070364],[-83.442052,45.051056],[-83.435822,45.000012],[-83.438856,44.940843],[-83.352815,44.886164],[-83.320503,44.880571],[-83.31626610857658,44.85859145056089],[-83.296971,44.758495],[-83.276836,44.689354],[-83.314517,44.608725],[-83.31696256841268,44.51173484788758],[-83.31761,44.486058],[-83.336988,44.332919],[-83.401822,44.301831],[-83.442731,44.265361],[-83.524817,44.261558],[-83.56464579249669,44.16352481840299],[-83.567744,44.155899],[-83.58409,44.056748],[-83.679654,44.036365],[-83.693214,43.98877],[-83.787863,43.985279],[-83.869406,43.960719],[-83.901329352181,43.90842705084419],[-83.910613,43.89322],[-83.929375,43.777091],[-83.94774,43.735165],[-83.909479,43.672622],[-83.817894,43.673789],[-83.731005,43.623369],[-83.69941709188109,43.60163715025649],[-83.683351,43.590584],[-83.52964047173398,43.71924491910489],[-83.51234,43.733726],[-83.50608555254279,43.74515721313988],[-83.479567,43.793625],[-83.43261,43.885273],[-83.407146,43.919807],[-83.28231,43.938031],[-83.26153,43.973525],[-83.134881,43.993147],[-83.046577,44.01571],[-83.024604,44.045174],[-82.928884,44.069389],[-82.793205,44.023247],[-82.709839,43.948226],[-82.633641,43.831224],[-82.612224,43.739771],[-82.60647742060837,43.690435],[-82.593785,43.581467],[-82.53993,43.422378],[-82.523086,43.225361],[-82.50604240495508,43.168827371311494],[-82.486042,43.102486],[-82.415937,43.005555],[-82.428603,42.952001],[-82.469912,42.887459],[-82.467483,42.76191],[-82.509935,42.637294],[-82.583996,42.554041],[-82.679059,42.52221],[-82.706371,42.621107],[-82.639701,42.661233],[-82.707885,42.675497],[-82.801022,42.629545],[-82.766004,42.600051],[-82.755927,42.564415],[-82.859316,42.541935],[-82.85944706548808,42.54085321960889],[-82.860210200131,42.534554505092494],[-82.86753194498138,42.4741227306931],[-82.87030495844998,42.451235],[-82.870347,42.450888],[-82.92397,42.352068],[-82.94967209864558,42.34426422122049],[-82.988619,42.332439],[-83.096521,42.290138],[-83.09785849625608,42.28601136524869],[-83.11568284140247,42.231017146190894],[-83.133923,42.17474],[-83.133511,42.088143],[-83.185526,42.052243],[-83.19490571413668,42.033202518164686],[-83.216897,41.988561],[-83.269521,41.939042],[-83.326024,41.924961],[-83.341557,41.879956],[-83.39622,41.852965],[-83.441668,41.808646],[-83.424076,41.740738],[-83.453832,41.732647],[-83.58554184210878,41.728772028512786],[-83.763038,41.72355],[-83.76314999206207,41.723546797762594],[-83.88039024525756,41.72019449661289],[-84.134417,41.712931],[-84.36041904139728,41.70695588263349],[-84.39954878547418,41.705921357405586],[-84.438067,41.704903],[-84.806082,41.696089],[-84.805883,41.760216],[-84.82512828387678,41.76019900635189],[-85.19677420030199,41.759870841802986],[-85.232835,41.759839],[-85.29217881133349,41.75975527470178],[-85.65975023799089,41.75923668604699],[-85.79133496196276,41.75905103955749],[-85.791363,41.759051],[-86.06256302901056,41.75965303315798],[-86.22607,41.760016],[-86.22609434498737,41.76001595911639],[-86.501773,41.759553],[-86.52421974244288,41.759572155973494],[-86.640044,41.759671],[-86.64132292052079,41.75967493814279],[-86.824828,41.76024],[-86.693267,41.835403]]],[[[-89.221332,47.908069],[-89.179154,47.93503],[-89.018303,47.992525],[-88.940886,48.01959],[-88.893701,48.03477],[-88.816084,48.057006],[-88.728198,48.101914],[-88.631908,48.148307],[-88.547033,48.174891],[-88.425162,48.21065],[-88.427373,48.166764],[-88.55044,48.102111],[-88.579172,48.040758],[-88.718555,47.995134],[-88.852923,47.965322],[-88.898986,47.900685],[-89.044463,47.85575],[-89.157738,47.824015],[-89.201812,47.850243],[-89.255202,47.876102],[-89.221332,47.908069]]],[[[-90.418136,46.566094],[-90.327626,46.607744],[-90.237609,46.624485],[-90.04542,46.668272],[-89.918466,46.740324],[-89.88386763801047,46.76581144666779],[-89.831956,46.804053],[-89.720277,46.830413],[-89.642255,46.82534],[-89.569808,46.831859],[-89.49908,46.841621],[-89.415154,46.843983],[-89.227914,46.912954],[-89.142595,46.984859],[-89.02893,47.00114],[-88.959409,47.008496],[-88.93336845134169,47.033599097856],[-88.924492,47.042156],[-88.88914,47.100575],[-88.814834,47.141399],[-88.69966,47.204831],[-88.584912,47.242361],[-88.51294650563608,47.28610724771499],[-88.50078,47.293503],[-88.418673,47.371188],[-88.285195,47.422392],[-88.217822,47.448738],[-88.085252,47.468961],[-87.929269,47.478737],[-87.801184,47.473301],[-87.680067,47.455685],[-87.591498,47.424113],[-87.604704,47.388625],[-87.800294,47.392148],[-87.941613,47.390073],[-87.94336,47.335899],[-88.016478,47.306275],[-88.096851,47.261351],[-88.194218,47.209242],[-88.20045067593368,47.199716895981986],[-88.239895,47.139436],[-88.340052,47.080494],[-88.385606,47.004522],[-88.43936318594379,46.94198242500038],[-88.455404,46.923321],[-88.477935,46.85056],[-88.372681,46.872277],[-88.244437,46.929612],[-88.143688,46.966665],[-88.065192,46.918563],[-88.04452168228147,46.91744994527619],[-87.900339,46.909686],[-87.77693,46.876726],[-87.687164,46.841742],[-87.595307,46.78295],[-87.573203,46.720471],[-87.503025,46.647497],[-87.381649,46.580059],[-87.366767,46.507303],[-87.175065,46.497548],[-87.11635958947068,46.50615140212049],[-86.976958,46.526581],[-86.903742,46.466138],[-86.810967,46.449663],[-86.750157,46.479109],[-86.695645,46.555026],[-86.62738,46.53371],[-86.557731,46.487434],[-86.45993,46.551928],[-86.188024,46.654008],[-86.138295,46.672935],[-85.995044,46.673676],[-85.86460714132917,46.686568315513384],[-85.841057,46.688896],[-85.482096,46.680432],[-85.25686,46.75338],[-85.23787317735956,46.755702781256495],[-85.173042,46.763634],[-84.964652,46.772845],[-85.028291,46.675125],[-85.027374,46.553756],[-84.969464,46.47629],[-84.849767,46.460245],[-84.678423,46.487694],[-84.607945,46.456747],[-84.493401,46.440313],[-84.461827,46.466566],[-84.420274,46.501077],[-84.293016,46.492803],[-84.193729,46.53992],[-84.117925,46.517619],[-84.125026,46.470143],[-84.138906,46.372221],[-84.097766,46.256512],[-84.108089,46.241238],[-84.114941,46.174114],[-84.026536,46.131648],[-83.974012,46.081552],[-83.882303,46.042065],[-83.815826,46.108529],[-83.719791,46.101031],[-83.598612,46.090085],[-83.480639,45.996164],[-83.526347,45.918636],[-83.583052,45.915919],[-83.65766,45.945463],[-83.80104,45.937582],[-83.910838,45.965613],[-84.080071,45.970822],[-84.11460656251879,45.967908374795385],[-84.254952,45.956068],[-84.376429,45.931962],[-84.480436,45.977764],[-84.567493,45.947702],[-84.632855,45.951007],[-84.734002,45.907026],[-84.706383,45.848658],[-84.792763,45.858691],[-84.917484,45.93067],[-85.003597,46.00613],[-85.152027,46.050725],[-85.266385,46.065779],[-85.381394,46.082044],[-85.540858,46.079581],[-85.648581,45.983695],[-85.697203,45.960158],[-85.810442,45.980087],[-85.86583992194267,45.94757107318528],[-85.913769,45.919439],[-86.072067,45.965313],[-86.278007,45.942057],[-86.349134,45.83416],[-86.439661,45.760669],[-86.45988051774937,45.75022655059599],[-86.54143,45.70811],[-86.616972,45.620581],[-86.636895,45.542053],[-86.712328,45.610939],[-86.705184,45.690901],[-86.647319,45.732618],[-86.773279,45.811385],[-86.838746,45.722307],[-86.964275,45.672761],[-87.070442,45.718779],[-87.172241,45.661788],[-87.25344962878017,45.550115590889085],[-87.288726,45.501606],[-87.350852,45.407743],[-87.465201,45.273351],[-87.548964,45.191591],[-87.590208,45.095264],[-87.648191,45.106368],[-87.695055,45.150522],[-87.741805,45.197051],[-87.71148,45.245224],[-87.667423,45.31636],[-87.657349,45.368752],[-87.706767,45.383827],[-87.750928,45.355037],[-87.800464,45.353608],[-87.863489,45.35302],[-87.85683,45.393106],[-87.847429,45.444177],[-87.805773,45.473139],[-87.804203,45.524676],[-87.787292,45.574906],[-87.777671,45.609204],[-87.824676,45.653211],[-87.781007,45.673934],[-87.805076,45.703556],[-87.83304946803528,45.72275257534689],[-87.879812,45.754843],[-87.96697,45.764021],[-87.995876,45.795435],[-88.048514,45.782549],[-88.05701046594899,45.784977030143686],[-88.105518,45.798839],[-88.135067,45.821694],[-88.073944,45.875593],[-88.115346,45.922211],[-88.11685653737608,45.92281124226269],[-88.178008,45.947111],[-88.246307,45.962983],[-88.30952,45.959369],[-88.380183,45.991654],[-88.409864,45.979688],[-88.526673,46.020822],[-88.59386,46.015132],[-88.613063,45.990627],[-88.65776,45.989287],[-88.679132,46.013538],[-88.68323220849936,46.014465670320284],[-88.739994,46.027308],[-88.811948,46.021609],[-88.93276845100957,46.07210716377599],[-88.99121702839598,46.09653635443599],[-89.09163,46.138505],[-89.638416,46.243804],[-89.92912562566477,46.29991572840809],[-90.120489,46.336852],[-90.158241,46.420485],[-90.214866,46.499947],[-90.285707,46.518846],[-90.331887,46.553278],[-90.387228,46.533663],[-90.418136,46.566094]]]]}}, {"type":"Feature","properties":{"name":"Missouri","income":{"1995":31701,"1996":32947,"1997":34502,"1998":37186,"1999":37885,"2000":40411,"2001":39652,"2002":40309,"2003":40870,"2004":40885,"2005":41946,"2006":42838,"2007":45012,"2008":46847,"2009":45149,"2010":44306,"2011":45231,"2012":45320,"2013":46905,"2014":48288,"2015":50200}},"geometry":{"type":"Polygon","coordinates":[[[-95.765645,40.585208],[-95.533182,40.582249],[-95.37392505339868,40.58033237794148],[-95.335588,40.579871],[-95.20226600083026,40.578375628995985],[-95.068921,40.57688],[-94.91489786736157,40.57492116911129],[-94.819978,40.573714],[-94.63202591769478,40.57175958739999],[-94.533878,40.570739],[-94.47120772712316,40.570959458356995],[-94.310724,40.571524],[-94.23224071020826,40.57201461212659],[-94.091085,40.572897],[-94.015492,40.57407370700959],[-93.84093,40.576791],[-93.77434420403027,40.577530453391084],[-93.597352,40.579496],[-93.55689667427168,40.57965948506049],[-93.37438625876378,40.580397032609184],[-93.345442,40.580514],[-93.135802,40.582854],[-93.09729120374978,40.58382347732509],[-92.941595,40.587743],[-92.71459726304498,40.589582833836296],[-92.686693,40.589809],[-92.63790329359948,40.59095654709789],[-92.453745,40.595288],[-92.35080418672638,40.59725727637609],[-92.17978,40.600529],[-91.94311745968568,40.606060586354],[-91.939292,40.60615],[-91.729115,40.61364],[-91.71665498768186,40.603740139295994],[-91.685381,40.578892],[-91.670993,40.550937],[-91.618999,40.539084],[-91.608347,40.50004],[-91.563844,40.460988],[-91.519134,40.432822],[-91.498093,40.401926],[-91.419422,40.378264],[-91.469656,40.322409],[-91.492891,40.269923],[-91.49695749033947,40.24870387637279],[-91.50616790862227,40.20064351279509],[-91.511956,40.170441],[-91.497663,40.078257],[-91.484064,40.019332],[-91.43709,39.946417],[-91.43684326859906,39.94524346367849],[-91.428956,39.907729],[-91.436051,39.84551],[-91.397853,39.821122],[-91.361571,39.787548],[-91.36461660332327,39.75871822632229],[-91.367753,39.729029],[-91.30576033496517,39.68621547007789],[-91.27614,39.665759],[-91.18287550081966,39.598233115795395],[-91.174232,39.591975],[-91.148275,39.545798],[-91.100307,39.538695],[-91.064305,39.494643],[-91.03827,39.448436],[-90.937419,39.400803],[-90.93534994636859,39.39951952890709],[-90.840106,39.340438],[-90.72996,39.255894],[-90.72328362341267,39.22410297005759],[-90.707902,39.15086],[-90.681086,39.10059],[-90.713629,39.053977],[-90.676397,38.984096],[-90.66158290687677,38.93470330775319],[-90.657254,38.92027],[-90.595354,38.87505],[-90.555693,38.870785],[-90.500117,38.910408],[-90.467784,38.961809],[-90.45096994089188,38.96139500332449],[-90.395816,38.960037],[-90.298711,38.923395],[-90.27658372202559,38.91933846721158],[-90.230336,38.91086],[-90.20728230118557,38.898732322839884],[-90.113327,38.849306],[-90.117707,38.805748],[-90.166409,38.772649],[-90.16659464001557,38.77245013930509],[-90.20991,38.72605],[-90.19521,38.68755],[-90.18152438153136,38.66037288531049],[-90.18111,38.65955],[-90.18451,38.611551],[-90.248913,38.544752],[-90.25529488766936,38.53087771182099],[-90.26097605928697,38.51852678740779],[-90.271314,38.496052],[-90.288815,38.438453],[-90.34024428170427,38.38709462263628],[-90.34291526673718,38.38442732002759],[-90.349743,38.377609],[-90.372519,38.323354],[-90.363926,38.236355],[-90.35116414506028,38.21954445709449],[-90.322353,38.181593],[-90.25274632397579,38.12777382622939],[-90.252484,38.127571],[-90.218708,38.094365],[-90.20572862588267,38.088233183108585],[-90.126006,38.05057],[-90.080959,38.015428],[-90.008353,37.970179],[-89.95491,37.966647],[-89.974221,37.919217],[-89.93309579091499,37.88009905825239],[-89.923185,37.870672],[-89.851048,37.90398],[-89.782035,37.855092],[-89.696559,37.814337],[-89.68722138085306,37.79640671843929],[-89.667993,37.759484],[-89.591289,37.723599],[-89.521948,37.696475],[-89.506563,37.62505],[-89.494051,37.580116],[-89.49774592603917,37.56998591392818],[-89.50179104949977,37.55889571932319],[-89.5124,37.52981],[-89.471201,37.466473],[-89.42594,37.407471],[-89.428185,37.356158],[-89.47367943454117,37.33485390219459],[-89.49516,37.324795],[-89.517032,37.28192],[-89.48288928464397,37.260950718414094],[-89.470525,37.253357],[-89.456105,37.18812],[-89.384175,37.103267],[-89.359456,37.042606],[-89.30743669117298,37.02875944962789],[-89.257608,37.015496],[-89.195039,36.989768],[-89.132915,36.982057],[-89.098843,36.95785],[-89.10313544832657,36.94476090032229],[-89.120472,36.891896],[-89.147674,36.847148],[-89.155891,36.789126],[-89.15598490907037,36.786292663371384],[-89.15699,36.755968],[-89.202511,36.716618],[-89.165488,36.662426],[-89.17564977234687,36.65131926255349],[-89.199136,36.625649],[-89.227319,36.569375],[-89.278935,36.577699],[-89.324658,36.624032],[-89.327319777009,36.62394628877049],[-89.378694,36.622292],[-89.407906,36.562345],[-89.479346,36.566253],[-89.544434,36.57451],[-89.571481,36.538087],[-89.539232,36.497934],[-89.521021,36.461934],[-89.542337,36.420103],[-89.51038,36.378356],[-89.522695,36.344789],[-89.54503133396906,36.344271398663],[-89.600544,36.342985],[-89.611819,36.309088],[-89.554289,36.277751],[-89.602374,36.238106],[-89.678046,36.248284],[-89.69263,36.224959],[-89.62764144167537,36.185460316606],[-89.623804,36.183128],[-89.592102,36.135637],[-89.64302,36.10362],[-89.680029,36.082494],[-89.692437,36.020507],[-89.733095,36.000608],[-89.901183,35.999365],[-89.95937529517369,35.99901411015688],[-90.103842,35.998143],[-90.28894791527279,35.99651400421139],[-90.368718,35.995812],[-90.339343,36.047112],[-90.294492,36.112949],[-90.235585,36.139474],[-90.220425,36.184764],[-90.18912798221689,36.19898660866739],[-90.155928,36.214074],[-90.114922,36.265595],[-90.06398,36.303038],[-90.063526,36.356911],[-90.066136,36.386272],[-90.131038,36.415069],[-90.141399,36.459874],[-90.153871,36.495344],[-90.22074905391537,36.495937592194494],[-90.494575,36.498368],[-90.57617906556729,36.498405927798],[-90.765672,36.498494],[-90.78424415513118,36.49846220012908],[-91.017974,36.498062],[-91.12653887456469,36.497797701019394],[-91.404915,36.49712],[-91.40713744351747,36.497140711948596],[-91.45000491813738,36.49754021318469],[-91.64259,36.499335],[-91.67234245644367,36.499256633798886],[-91.985802,36.498431],[-92.12042910438808,36.49819312399969],[-92.15030624950118,36.498140333324194],[-92.350277,36.497787],[-92.52913658104367,36.498165682985295],[-92.564238,36.49824],[-92.77233389337206,36.498083154079396],[-92.838876,36.498033],[-92.85404911498487,36.498023381141586],[-93.125969,36.497851],[-93.29344735563399,36.49825937523429],[-93.31532710652907,36.49831272629789],[-93.426989,36.498585],[-93.58428154735566,36.498901678628286],[-93.700171,36.499135],[-93.86675821167105,36.49886616468489],[-93.95919,36.498717],[-94.07708826689347,36.49897595722189],[-94.361203,36.4996],[-94.617919,36.499414],[-94.617815,36.612604],[-94.61799177841718,36.66792127234419],[-94.618307,36.76656],[-94.617964,36.998905],[-94.61810289110298,37.05679639087289],[-94.618351,37.160211],[-94.61775389160657,37.338418],[-94.61766760470077,37.36417032703869],[-94.617511,37.410909],[-94.6178455243542,37.653577796634394],[-94.61787245089806,37.673110700332096],[-94.617885,37.682214],[-94.614465,37.987799],[-94.61410024870548,38.03705658338129],[-94.61392996105577,38.06005295989649],[-94.612614,38.237766],[-94.61277262899287,38.38871848273179],[-94.612866,38.477571],[-94.61286559592209,38.47760218023509],[-94.61195801832227,38.547634434271686],[-94.60948967234579,38.73810170947319],[-94.609456,38.7407],[-94.60896034374949,38.84721131544499],[-94.608334,38.981806],[-94.60787035337397,39.04408509647849],[-94.607354,39.113444],[-94.591933,39.155003],[-94.60193798192108,39.15550323346379],[-94.623934,39.156603],[-94.680336,39.184303],[-94.741938,39.170203],[-94.79199467374328,39.20126025024019],[-94.799663,39.206018],[-94.825663,39.241729],[-94.857072,39.273825],[-94.908065,39.323663],[-94.888972,39.392432],[-94.946662,39.399717],[-94.96574741863347,39.42168174465639],[-94.982144,39.440552],[-95.049845,39.494415],[-95.09141940282399,39.53325788520999],[-95.113557,39.553941],[-95.076688,39.576764],[-95.047165,39.595117],[-95.04405075257039,39.61366829682089],[-95.037464,39.652905],[-94.971317,39.68641],[-94.971078,39.723146],[-94.899316,39.724042],[-94.860371,39.74953],[-94.871144,39.772994],[-94.87781752985117,39.82041477603549],[-94.878677,39.826522],[-94.928466,39.876344],[-94.95154,39.900533],[-94.99337423971437,39.89856525999229],[-95.018743,39.897372],[-95.081534,39.861718],[-95.142445,39.89542],[-95.231114,39.943784],[-95.30829,39.999998],[-95.348777,40.029297],[-95.382957,40.027112],[-95.414734,40.06982],[-95.394216,40.108263],[-95.432165,40.141025],[-95.48102,40.188524],[-95.472548,40.236078],[-95.54716,40.259066],[-95.54787031627028,40.26278346081979],[-95.54818200118008,40.26441467284269],[-95.553292,40.291158],[-95.598657,40.309809],[-95.653729,40.322582],[-95.641027,40.366399],[-95.649418,40.396149],[-95.684363,40.463366],[-95.694726,40.493602],[-95.71228037180106,40.52375442620738],[-95.714291,40.527208],[-95.75711,40.52599],[-95.765645,40.585208]]]}}, {"type":"Feature","properties":{"name":"Montana","income":{"1995":27889,"1996":28714,"1997":29672,"1998":31271,"1999":32098,"2000":33281,"2001":33151,"2002":34105,"2003":34449,"2004":35574,"2005":38503,"2006":40299,"2007":43000,"2008":43948,"2009":42222,"2010":42303,"2011":44011,"2012":45030,"2013":46893,"2014":46608,"2015":49650}},"geometry":{"type":"Polygon","coordinates":[[[-116.049193,49.000912],[-115.501016,49.000694],[-115.207912,48.999228],[-114.72704522327697,49.00058700388858],[-114.678217,49.000725],[-114.375977,49.00139],[-114.180211,48.999703],[-114.06817845427997,48.99935588166379],[-113.907487,48.998858],[-113.692982,48.997632],[-113.375925,48.998562],[-113.116356,48.998462],[-112.19341019591398,48.99889377663368],[-112.143769,48.998917],[-111.854088,48.998067],[-111.500812,48.996963],[-111.26986200082898,48.99722978681158],[-111.003916,48.997537],[-110.743064,48.99800811218479],[-110.531615,48.99839],[-110.438151,48.999188],[-110.171595,48.999262],[-109.500737,49.00044],[-109.48954977898597,49.00042080388049],[-109.250722,49.000011],[-109.000708,48.999234],[-108.543194,48.999377],[-108.236393,48.99955811730138],[-107.704696,48.999872],[-107.441017,48.999363],[-107.363582,49.000019],[-107.17981201253797,48.999911601747385],[-106.617539,48.999583],[-106.233987,48.999423],[-106.11206332368398,48.999279438400286],[-106.050543,48.999207],[-105.775808,48.999637],[-105.355888,48.999357],[-105.265192,48.9995],[-105.057641716691,48.99922888739248],[-104.875527,48.998991],[-104.543636,48.999541],[-104.048736,48.999877],[-104.0489,48.847387],[-104.04808756883199,48.63401237339858],[-104.047555,48.49414],[-104.04678216170598,48.38930073114548],[-104.045692,48.241415],[-104.04409327282099,47.99610717418708],[-104.04409321534798,47.99609835556468],[-104.043933,47.971515],[-104.042384,47.803256],[-104.043912,47.603229],[-104.04497671640497,47.397069201282385],[-104.045313,47.331955],[-104.04530830986899,47.330127858805994],[-104.044788,47.12743],[-104.045542,46.933887],[-104.045572,46.713881],[-104.045385103689,46.641501059121794],[-104.04512541332298,46.540929928548984],[-104.045045,46.509788],[-104.045469,46.324545],[-104.04546595892799,46.28018804821068],[-104.045443,45.94531],[-104.04413315610697,45.88197625834978],[-104.043776,45.864707],[-104.042597,45.749998],[-104.041937,45.557915],[-104.041764,45.490789],[-104.040358,45.335946],[-104.04013575649299,45.21289076204159],[-104.039977,45.124988],[-104.039138,44.99852],[-104.057698,44.997431],[-105.025266,45.00029],[-105.03825218827397,45.00029167299179],[-105.07660095225397,45.000296613407386],[-105.848065,45.000396],[-106.02488002903198,44.99758412355609],[-106.263586,44.993788],[-106.26371509246498,44.99378843300149],[-106.888773,44.995885],[-107.351441,45.001407],[-107.91152278816197,45.00154400461138],[-107.997353,45.001565],[-108.24852773809597,45.00062981791279],[-108.500679,44.999691],[-108.62149349472998,44.99967637102149],[-109.062262,44.999623],[-109.103445,45.005904],[-109.574321,45.002631],[-109.79848377243498,45.002920308285],[-109.99505,45.003174],[-110.324441,44.999156],[-110.705272,44.992324],[-110.785008,45.002952],[-111.044275,45.001345],[-111.04431854542997,45.000880003307685],[-111.056888,44.866658],[-111.055511,44.725343],[-111.05533272712397,44.66626230991749],[-111.055208,44.624927],[-111.048974,44.474072],[-111.122654,44.493659],[-111.143557,44.535732],[-111.201459,44.575696],[-111.224161,44.623402],[-111.26875,44.668279],[-111.323669,44.724474],[-111.37713823673496,44.75119641396359],[-111.385005,44.755128],[-111.438793,44.720546],[-111.45694723249397,44.69564073783949],[-111.468833,44.679335],[-111.519126,44.582916],[-111.562814,44.555209],[-111.61710703430498,44.55712724841859],[-111.704218,44.560205],[-111.807914,44.511716],[-111.870504,44.564033],[-112.034133,44.537716],[-112.125101,44.528527],[-112.221698,44.543519],[-112.286187,44.568472],[-112.358917,44.528847],[-112.387389,44.448058],[-112.473207,44.480027],[-112.601863,44.491015],[-112.707815,44.503023],[-112.735084,44.499159],[-112.828191,44.442472],[-112.821896,44.407436],[-112.82682688126498,44.40520243176749],[-112.881769,44.380315],[-112.951146,44.416699],[-113.006846,44.471715],[-113.006828,44.518439],[-113.061071,44.577329],[-113.049349,44.62938],[-113.101154,44.708578],[-113.131387,44.764738],[-113.247166,44.82295],[-113.301508,44.798985],[-113.377153,44.834858],[-113.422376,44.842595],[-113.474573,44.910846],[-113.448958,44.953544],[-113.437726,45.006967],[-113.45197,45.059247],[-113.510819,45.099902],[-113.57467,45.128411],[-113.650064,45.23471],[-113.735601,45.325265],[-113.73239,45.385058],[-113.763368,45.427732],[-113.759986,45.480735],[-113.802849,45.523159],[-113.806729,45.602146],[-113.861404,45.62366],[-113.898883,45.644167],[-113.94832148257,45.68257735844148],[-113.971565,45.700636],[-114.015633,45.696127],[-114.014973,45.654008],[-114.083149,45.603996],[-114.18647,45.545539],[-114.251836,45.537812],[-114.279217,45.480616],[-114.36852,45.492716],[-114.456764,45.543983],[-114.506341,45.559216],[-114.52371067493497,45.58523308600019],[-114.538132,45.606834],[-114.53577,45.650613],[-114.499637,45.669035],[-114.504869,45.722176],[-114.562509,45.779927],[-114.517143,45.835993],[-114.422963,45.855381],[-114.388243,45.88234],[-114.413168,45.911479],[-114.402261,45.961489],[-114.441185,45.988453],[-114.480241,46.030325],[-114.460049,46.097104],[-114.5213,46.125287],[-114.514706,46.167726],[-114.445928,46.173933],[-114.449819,46.237119],[-114.441326,46.2738],[-114.431708,46.310744],[-114.422458,46.387097],[-114.384756,46.411784],[-114.403019,46.498675],[-114.351655,46.508119],[-114.331338,46.577781],[-114.320665,46.646963],[-114.33572493540497,46.65527296735359],[-114.360709,46.669059],[-114.453239,46.649266],[-114.547321,46.644485],[-114.59124789474797,46.65257477007719],[-114.621483,46.658143],[-114.626695,46.712889],[-114.67682716269498,46.73183873981309],[-114.699008,46.740223],[-114.76718,46.738828],[-114.79004,46.778729],[-114.880588,46.811791],[-114.943281,46.867971],[-114.927432,46.914185],[-114.961422906068,46.932893875970784],[-115.031651,46.971548],[-115.071254,47.022083],[-115.120917,47.061237],[-115.189451,47.131032],[-115.255786,47.174725],[-115.29211,47.209861],[-115.326903,47.255912],[-115.371825,47.265213],[-115.470959,47.284873],[-115.531971,47.314121],[-115.578619,47.367007],[-115.71034,47.417784],[-115.69293,47.457237],[-115.634684,47.48176],[-115.717024,47.532693],[-115.721207,47.576323],[-115.694284,47.62346],[-115.73627,47.654762],[-115.72377,47.696671],[-115.835365,47.760957],[-115.845474,47.814967],[-115.900934,47.843064],[-115.959946,47.898142],[-116.030751,47.973349],[-116.03856582987298,47.98463425644169],[-116.049153,47.999923],[-116.048911,48.12493],[-116.04892924777596,48.216127947927085],[-116.048948,48.309847],[-116.049155,48.481247],[-116.04915652064899,48.50204248175808],[-116.049193,49.000912]]]}}, {"type":"Feature","properties":{"name":"New York","income":{"1995":33805,"1996":35696,"1997":36369,"1998":38290,"1999":41047,"2000":41763,"2001":43149,"2002":42765,"2003":44139,"2004":45343,"2005":49365,"2006":51340,"2007":53448,"2008":55980,"2009":54554,"2010":54047,"2011":55147,"2012":56357,"2013":57255,"2014":58771,"2015":60805}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-72.018926,41.274114],[-71.926802,41.290122],[-71.917281,41.251333],[-72.034754,41.234818],[-72.018926,41.274114]]],[[[-79.761951,42.26986],[-79.627484,42.324686],[-79.453533,42.411157],[-79.381943,42.466491],[-79.283364,42.511228],[-79.193232,42.545881],[-79.138569,42.564462],[-79.13594440402159,42.569178709973585],[-79.111361,42.613358],[-79.06376,42.644758],[-79.04886,42.689158],[-78.972378,42.715991],[-78.904843,42.746121],[-78.851355,42.791758],[-78.85688499234988,42.80529199987729],[-78.865656,42.826758],[-78.882557,42.867258],[-78.912458,42.886557],[-78.909159,42.933257],[-78.927957,42.952922],[-78.961761,42.957756],[-79.019964,42.994756],[-79.00545,43.057231],[-79.018246,43.066016],[-79.01957788489429,43.066296467890396],[-79.074467,43.077855],[-79.060206,43.124799],[-79.05525244093957,43.133812266616985],[-79.044567,43.153255],[-79.052868,43.222054],[-79.070469,43.262454],[-78.834061,43.317555],[-78.547395,43.369541],[-78.46555118759608,43.370895422166384],[-78.329374,43.373149],[-78.145195,43.37551],[-77.99558979493837,43.36531025567759],[-77.994838,43.365259],[-77.816533,43.34356],[-77.80826340960718,43.34320763689829],[-77.760231,43.341161],[-77.660359,43.282998],[-77.551022,43.235763],[-77.50092,43.250363],[-77.37605199595338,43.27403376348698],[-77.341092,43.280661],[-77.264177,43.277363],[-77.130429,43.285635],[-76.999691,43.271456],[-76.952174,43.270692],[-76.841675,43.305399],[-76.769025,43.318452],[-76.72200256571277,43.33758019598139],[-76.684856,43.352691],[-76.630774,43.413356],[-76.61721373257758,43.420175554465594],[-76.515882,43.471136],[-76.417581,43.521285],[-76.37094283766898,43.52562706153029],[-76.368849,43.525822],[-76.319701,43.512275],[-76.235834,43.529256],[-76.203473,43.574978],[-76.196596,43.649761],[-76.20148254738568,43.68028596022369],[-76.213205,43.753513],[-76.229268,43.804135],[-76.296758,43.857079],[-76.361037,43.872585],[-76.441848,43.882864],[-76.412138,43.925676],[-76.279314,43.972462],[-76.307674,44.025277],[-76.37556,44.031536],[-76.361836,44.072721],[-76.370706,44.100499],[-76.355679,44.133258],[-76.334584,44.164945],[-76.286547,44.203773],[-76.206777,44.214543],[-76.164265,44.239603],[-76.161833,44.280777],[-76.097351,44.299547],[-76.000998,44.347534],[-75.94954,44.349129],[-75.86127119283468,44.40519201350308],[-75.834126,44.422433],[-75.807778,44.471644],[-75.76623,44.515851],[-75.567413,44.658709],[-75.423943,44.756329],[-75.333744,44.806378],[-75.255517,44.857651],[-75.142958,44.900237],[-75.066245,44.930174],[-75.005155,44.958402],[-74.992756,44.977449],[-74.907956,44.983359],[-74.834669,45.014683],[-74.74464,44.990577],[-74.72581343161899,44.99179262652589],[-74.64473931982567,44.99702756041669],[-74.611048,44.999203],[-74.436934,44.996177],[-74.234136,44.992148],[-74.02743141336848,44.99736535923969],[-73.874597,45.001223],[-73.639718,45.003464],[-73.343124,45.01084],[-73.34474,44.970468],[-73.338979,44.917681],[-73.379822,44.857037],[-73.365678,44.826451],[-73.34201248394999,44.80807553866099],[-73.33443,44.802188],[-73.357671,44.751018],[-73.36556,44.700297],[-73.389966,44.61962],[-73.367275,44.567545],[-73.36268281274378,44.56245522168669],[-73.34798323242649,44.54616285359699],[-73.312871,44.507246],[-73.293613,44.440559],[-73.320954,44.382669],[-73.334637,44.356877],[-73.324229,44.310023],[-73.31745597466508,44.26352218987678],[-73.316618,44.257769],[-73.349889,44.230356],[-73.395399,44.166903],[-73.39986856936459,44.152485647691684],[-73.416319,44.099422],[-73.43688,44.042578],[-73.405977,44.011485],[-73.411248,43.975596],[-73.407742,43.929887],[-73.374051,43.875563],[-73.390302,43.817371],[-73.38252614953988,43.80815898854949],[-73.350707,43.770463],[-73.36110715168428,43.75323345728389],[-73.393723,43.6992],[-73.414546,43.658209],[-73.424977,43.598775],[-73.395767,43.568087],[-73.327702,43.625913],[-73.292113,43.584509],[-73.242042,43.534925],[-73.252832,43.363493],[-73.25535583805758,43.314712398599994],[-73.26978,43.035923],[-73.27000873116357,43.030714292687485],[-73.273832807021,42.94363174752649],[-73.278673,42.83341],[-73.290944,42.80192],[-73.264957,42.74594],[-73.30700407618058,42.63265345141149],[-73.35252495494419,42.51000750995059],[-73.352527,42.510002],[-73.38350565728358,42.42564605018379],[-73.41064440742727,42.35174629964789],[-73.508142,42.086257],[-73.48967994203208,42.05379770958669],[-73.487314,42.049638],[-73.505008,41.823773],[-73.51791879063818,41.666720530709995],[-73.520017,41.641197],[-73.52967771430127,41.527161021128286],[-73.536969,41.441094],[-73.54314734626546,41.37677066829739],[-73.54318320799626,41.376397308516786],[-73.54330658069169,41.375112864027685],[-73.54415118640058,41.36631959624439],[-73.550961,41.295422],[-73.482709,41.21276],[-73.69593580216956,41.11525545690408],[-73.727775,41.100696],[-73.659533,41.017857],[-73.659362,41.004034],[-73.65737400926137,40.98552488385919],[-73.657336,40.985171],[-73.697974,40.939598],[-73.756776,40.912599],[-73.766276,40.881099],[-73.74119724494858,40.875854592837385],[-73.713674,40.870099],[-73.654372,40.878199],[-73.617571,40.897898],[-73.499941,40.918166],[-73.49735103862628,40.92318227329439],[-73.485365,40.946397],[-73.436664,40.934897],[-73.392862,40.955297],[-73.33136,40.929597],[-73.2358261228726,40.90668945969559],[-73.229285,40.905121],[-73.148994,40.928898],[-73.144673,40.955842],[-73.110368,40.971938],[-73.040445,40.964498],[-72.859831,40.966088],[-72.708069,40.977851],[-72.585327,40.997587],[-72.504305,41.043329],[-72.445242,41.086116],[-72.389809,41.108304],[-72.354123,41.139952],[-72.291109,41.155874],[-72.189163,41.193549],[-72.182033,41.178345],[-72.254704,41.110852],[-72.283093,41.067874],[-72.217476,41.040611],[-72.162898,41.053187],[-72.126704,41.115139],[-72.084207,41.101524],[-72.095711,41.05402],[-72.051928,41.020506],[-71.959595,41.071237],[-71.919385,41.080517],[-71.856214,41.070598],[-71.936977,41.006137],[-72.097369,40.95888],[-72.298727,40.903151],[-72.39585,40.86666],[-72.757176,40.764371],[-72.923214,40.713282],[-73.012545,40.679651],[-73.14608086921076,40.646407968101286],[-73.20844,40.630884],[-73.306396,40.620756],[-73.351465,40.6305],[-73.42397661755719,40.613244877559495],[-73.48486839434707,40.59875485376009],[-73.507325,40.593411],[-73.640902,40.582823],[-73.75062172165627,40.589319767127684],[-73.774928,40.590759],[-73.82549400113108,40.57614957899389],[-73.940591,40.542896],[-73.97379177024457,40.560854702517894],[-73.991346,40.57035],[-74.03655765445397,40.588988413741596],[-74.03797052391579,40.589570866339486],[-74.057316,40.597546],[-74.112585,40.547603],[-74.199923,40.511729],[-74.260611,40.502436],[-74.249211,40.545064],[-74.216839,40.558618],[-74.203688,40.592691],[-74.202247,40.630903],[-74.20012290199108,40.63186890194569],[-74.170611,40.645289],[-74.16014678315318,40.64607651644479],[-74.086806,40.651596],[-74.07094353771528,40.66720823277558],[-74.06772033031899,40.67038059424459],[-74.047313,40.690466],[-74.046966591833,40.69114928026859],[-74.04115624430348,40.70261002570879],[-74.03092708568377,40.72278675049359],[-74.02947453619967,40.72565186308668],[-74.02349153373218,40.73745316548729],[-74.013784,40.756601],[-73.98459249468017,40.79754332855229],[-73.97120801828238,40.81631562632088],[-73.968082,40.8207],[-73.96583451704629,40.82474525955859],[-73.94748456908319,40.85777345328739],[-73.938081,40.874699],[-73.93489258096068,40.88264898194209],[-73.92203089786648,40.914718213458784],[-73.92047152937927,40.918606332041],[-73.90728,40.951498],[-73.893979,40.997197],[-73.89398186003588,40.997198203538886],[-74.041054,41.059088],[-74.21161764319858,41.132981363536295],[-74.23436283123036,41.142835271534594],[-74.234473,41.142883],[-74.301994,41.172594],[-74.36703826144738,41.20421147244379],[-74.457584,41.248225],[-74.694914,41.357423],[-74.734893,41.425818],[-74.75627183472518,41.42762742854339],[-74.799546,41.43129],[-74.890358,41.455324],[-74.982463,41.496467],[-75.043879,41.575094],[-75.04619860591167,41.60376401990269],[-75.049281,41.641862],[-75.053431,41.752538],[-75.074412,41.802191],[-75.113369,41.840698],[-75.14666489928587,41.85012593014629],[-75.190203,41.862454],[-75.263005,41.885109],[-75.291762,41.947092],[-75.341125,41.992772],[-75.35985992915047,41.993685888904594],[-75.477144,41.999407],[-75.48314927095889,41.999398164522695],[-75.55311253909508,41.999295228473486],[-75.870677,41.998828],[-76.10584,41.998858],[-76.14551899478208,41.998866463308],[-76.462155,41.998934],[-76.47303088580799,41.999072381007],[-76.55762414356937,42.000148716341684],[-76.558118,42.000155],[-76.92684636295428,42.00072345181729],[-76.96572875942668,42.00078339504688],[-77.007635,42.000848],[-77.61002011447597,41.99914985407959],[-77.74993092512727,41.99875544032899],[-77.83203,41.998524],[-78.031177,41.999415],[-78.20660303785819,41.99908830575759],[-78.271204,41.998968],[-78.30812896044657,41.99907113474139],[-78.59665,41.999877],[-78.91885736361519,41.99910319868938],[-78.983065,41.998949],[-79.06126440315988,41.998838109911],[-79.472472,41.998255],[-79.61083577498667,41.99851990410838],[-79.761313,41.998808],[-79.762122,42.131246],[-79.761951,42.26986]]]]}}, {"type":"Feature","properties":{"name":"Oregon","income":{"1995":34533,"1996":35144,"1997":37284,"1998":38773,"1999":40033,"2000":41662,"2001":41752,"2002":41796,"2003":42593,"2004":42568,"2005":43065,"2006":46228,"2007":48735,"2008":50165,"2009":48325,"2010":46536,"2011":46876,"2012":49090,"2013":50228,"2014":51088,"2015":54074}},"geometry":{"type":"Polygon","coordinates":[[[-124.552441,42.840568],[-124.480938,42.951495],[-124.47988222693196,42.95432243767739],[-124.436198,43.071312],[-124.41139,43.159853],[-124.395607,43.223908],[-124.38246,43.270167],[-124.400404,43.302121],[-124.353332,43.342667],[-124.286896,43.436296],[-124.233534,43.55713],[-124.21905767690596,43.61093175918899],[-124.193455,43.706085],[-124.16020731587598,43.86372050152159],[-124.150267,43.91085],[-124.122406,44.104442],[-124.111054,44.235071],[-124.11437007425798,44.276194],[-124.1152,44.286486],[-124.084401,44.415611],[-124.083601,44.501123],[-124.065008,44.632504],[-124.063406,44.703177],[-124.074066,44.798107],[-124.063155,44.835333],[-124.023834,44.949825],[-124.01009720988498,45.044998959441195],[-124.00977,45.047266],[-123.975425,45.145476],[-123.972919,45.216784],[-123.962887,45.280218],[-123.979715,45.347724],[-123.960557,45.430778],[-123.976544,45.489733],[-123.947556,45.564878],[-123.939005,45.661923],[-123.939448,45.708795],[-123.968563,45.757019],[-123.96627838451897,45.78308490354529],[-123.961544,45.837101],[-123.96763,45.907807],[-123.993703,45.946431],[-123.937471,45.977306],[-123.92933,46.041978],[-123.95919,46.141675],[-124.041128,46.197672],[-123.998052,46.235327],[-123.912405,46.17945],[-123.838801,46.192211],[-123.757589,46.213001],[-123.718149,46.188989],[-123.660868,46.216296],[-123.586205,46.228654],[-123.547659,46.259109],[-123.479644,46.269131],[-123.427629,46.229348],[-123.430847,46.181827],[-123.371433,46.146372],[-123.36374450726598,46.14624319434849],[-123.280166,46.144843],[-123.21249359120895,46.171096458400285],[-123.166414,46.188973],[-123.115904,46.185268],[-123.004233,46.133823],[-122.962681,46.104817],[-122.904119,46.083734],[-122.856158,46.014469],[-122.813998,45.960984],[-122.81151,45.912725],[-122.785026,45.867699],[-122.788086362595,45.851007454356086],[-122.795605,45.81],[-122.761451,45.759163],[-122.76651077132999,45.728662574445195],[-122.774511,45.680437],[-122.75644390397096,45.66242102508758],[-122.738109,45.644138],[-122.643907,45.609739],[-122.492259,45.583281],[-122.438674,45.563585],[-122.380302,45.575941],[-122.331502,45.548241],[-122.262625,45.544321],[-122.24919700805198,45.54999893274119],[-122.183695,45.577696],[-122.101675,45.583516],[-122.00369,45.61593],[-121.951838,45.644951],[-121.92374936198499,45.65434950896938],[-121.900858,45.662009],[-121.867167,45.693277],[-121.811304,45.706761],[-121.735104,45.694039],[-121.668362,45.705082],[-121.533106,45.726541],[-121.52400610421999,45.72383622519919],[-121.44069582786098,45.69907379477239],[-121.423592,45.69399],[-121.33777,45.704949],[-121.215779,45.671238],[-121.183841,45.606441],[-121.1222,45.616067],[-121.084933,45.647893],[-120.943977,45.656445],[-120.91393501308399,45.64806586642348],[-120.895575,45.642945],[-120.855674,45.671545],[-120.68937,45.715847],[-120.65251676019399,45.73616973067489],[-120.634968,45.745847],[-120.591166,45.746547],[-120.505863,45.700048],[-120.48854682070397,45.69991222747849],[-120.40396,45.699249],[-120.282156,45.72125],[-120.210754,45.725951],[-120.141352,45.773152],[-120.07015,45.785152],[-119.99950515346198,45.81168492308189],[-119.965744,45.824365],[-119.868153889391,45.838226602635686],[-119.802655,45.84753],[-119.669877,45.856867],[-119.600549,45.919581],[-119.571584,45.925456],[-119.487829,45.906307],[-119.43213855881598,45.91320914423389],[-119.364396,45.921605],[-119.25715,45.939926],[-119.12612,45.932859],[-119.061462,45.958527],[-118.98722753956497,45.99980021352369],[-118.987129,45.999855],[-118.67787,46.000935],[-118.60678915418896,46.00086324979118],[-118.36779,46.000622],[-117.99697042960298,46.00019066717259],[-117.97765730653197,46.00016820238199],[-117.717852,45.999866],[-117.60342583450398,45.99876017344268],[-117.47993726365397,45.99756676684219],[-117.353928,45.996349],[-116.915989,45.995413],[-116.886843,45.958617],[-116.859795,45.907264],[-116.79920453250098,45.851045435482895],[-116.78752,45.840204],[-116.736268,45.826179],[-116.665344,45.781998],[-116.593004,45.778541],[-116.535698,45.734231],[-116.528272,45.681473],[-116.463504,45.615785],[-116.502756,45.566608],[-116.588195,45.44292],[-116.674648,45.314342],[-116.69092662009098,45.26895523844489],[-116.696047,45.254679],[-116.754643,45.113972],[-116.78312826326696,45.07771250500999],[-116.78371,45.076972],[-116.841314,45.030907],[-116.858313,44.978761],[-116.833632,44.928976],[-116.865338,44.870599],[-116.88929518696699,44.84052977815328],[-116.9318,44.787181],[-117.013802,44.756841],[-117.062273,44.727143],[-117.094968,44.652011],[-117.14293,44.557236],[-117.167187,44.523431],[-117.225932,44.479389],[-117.215072,44.427162],[-117.243027,44.390974],[-117.216911,44.360163],[-117.192203,44.32863],[-117.21199550695297,44.29645109593828],[-117.216974,44.288357],[-117.170342,44.25889],[-117.121037,44.277585],[-117.059352,44.237244],[-116.971958,44.235677],[-116.965498,44.194126],[-116.902752,44.179467],[-116.895931,44.154295],[-116.89785467711496,44.15266639539139],[-116.977351,44.085364],[-116.937342,44.029376],[-116.959871,43.982925],[-116.976024,43.895548],[-116.98554503848997,43.88118485281379],[-117.023577,43.823811],[-117.02566381044599,43.68029363595399],[-117.026889,43.596033],[-117.026652,43.025128],[-117.026253,42.807447],[-117.026551,42.378557],[-117.026197,41.99989],[-117.197798,42.00038],[-117.403613,41.99929],[-117.623731,41.998467],[-117.873467,41.998335],[-118.197189,41.996995],[-118.19736921592799,41.996994081163486],[-118.501002,41.995446],[-118.775869,41.992692],[-119.001022,41.993793],[-119.20828,41.993177],[-119.32418412043896,41.99387562779329],[-119.36012311960299,41.99409225498119],[-119.72573,41.996296],[-119.999168,41.99454],[-120.181563,41.994588],[-120.501069,41.993785],[-120.692219,41.993677],[-120.87992571023597,41.993483259984885],[-121.035195,41.993323],[-121.251099,41.99757],[-121.43961,41.99708],[-121.44753999804797,41.99719003327258],[-121.675348,42.000351],[-121.846712,42.00307],[-122.101922,42.005766],[-122.289527,42.007764],[-122.289749096157,42.00776473049658],[-122.501135,42.00846],[-122.80008,42.004071],[-123.045254,42.003049],[-123.145959,42.009247],[-123.23100126057798,42.00497006225599],[-123.347562,41.999108],[-123.43477,42.001641],[-123.51911283680398,41.999172518032886],[-123.656998,41.995137],[-123.82203759858797,41.995620816946996],[-124.001188,41.996146],[-124.211605,41.99846],[-124.270464,42.045553],[-124.314289,42.067864],[-124.351535,42.129796],[-124.361009,42.180752],[-124.383633,42.22716],[-124.410982,42.250547],[-124.410556,42.307431],[-124.425554,42.351874],[-124.435105,42.440163],[-124.399065,42.539928],[-124.400918,42.597518],[-124.413119,42.657934],[-124.45074,42.675798],[-124.448418,42.689909],[-124.510017,42.734746],[-124.552441,42.840568]]]}}, {"type":"Feature","properties":{"name":"Tennessee","income":{"1995":30016,"1996":31097,"1997":32047,"1998":34188,"1999":35624,"2000":35760,"2001":36629,"2002":37129,"2003":37925,"2004":38945,"2005":38947,"2006":40368,"2007":42389,"2008":43610,"2009":41715,"2010":41461,"2011":41691,"2012":42743,"2013":44268,"2014":44357,"2015":47243}},"geometry":{"type":"Polygon","coordinates":[[[-90.300697,35.028793],[-90.265296,35.040293],[-90.197146,35.050731],[-90.181387,35.091401],[-90.160058,35.12883],[-90.09061,35.118287],[-90.099777,35.164474],[-90.093285,35.203282],[-90.097947,35.249983],[-90.166594,35.274588],[-90.121864,35.304535],[-90.087903,35.36327],[-90.112504,35.410153],[-90.070549,35.423291],[-90.045306,35.415435],[-90.022064,35.457375],[-90.045805,35.496533],[-90.037615,35.550329],[-89.958498,35.541703],[-89.944754,35.560308],[-89.9325,35.607865],[-89.876548,35.626653],[-89.898916,35.650904],[-89.956589,35.695486],[-89.915491,35.754917],[-89.863874,35.747592],[-89.797053,35.782648],[-89.723426,35.809382],[-89.729517,35.847632],[-89.722634,35.873718],[-89.64727,35.89492],[-89.64890497034517,35.90358348231259],[-89.652279,35.921462],[-89.686924,35.947716],[-89.733095,36.000608],[-89.692437,36.020507],[-89.680029,36.082494],[-89.64302,36.10362],[-89.592102,36.135637],[-89.623804,36.183128],[-89.62764144167537,36.185460316606],[-89.69263,36.224959],[-89.678046,36.248284],[-89.602374,36.238106],[-89.554289,36.277751],[-89.611819,36.309088],[-89.600544,36.342985],[-89.54503133396906,36.344271398663],[-89.522695,36.344789],[-89.51038,36.378356],[-89.542337,36.420103],[-89.521021,36.461934],[-89.539232,36.497934],[-89.417293,36.499033],[-89.34519431953878,36.50134320863689],[-89.211409,36.50563],[-88.964471,36.502191],[-88.83458902287427,36.50198034225929],[-88.82717803634047,36.50196832225689],[-88.81676415734808,36.50195143181319],[-88.51635805997938,36.50146419816328],[-88.51192,36.501457],[-88.48907673871317,36.501283719075694],[-88.127378,36.49854],[-88.05335080077587,36.49999625068159],[-88.050466,36.500053],[-88.033802,36.551733],[-88.055738,36.630475],[-88.070532,36.678118],[-88.011792,36.677025],[-87.849567,36.663701],[-87.853204,36.633247],[-87.69418590786428,36.63683824394369],[-87.64115,36.638036],[-87.64114589700208,36.63803604761009],[-87.347796,36.64144],[-87.33597905008078,36.64157716049309],[-87.1150035566884,36.64414204465119],[-87.06082634439286,36.64477088485159],[-86.813037,36.647647],[-86.76329096410846,36.64872067450179],[-86.606394,36.652107],[-86.56206765186529,36.640746673907294],[-86.551292,36.637985],[-86.507771,36.652445],[-86.41149619896639,36.6482404228482],[-86.20556526985598,36.63924687032879],[-86.081944,36.633848],[-85.97571317414399,36.62863771868169],[-85.873857,36.623642],[-85.78855654361386,36.62171185903469],[-85.731862,36.620429],[-85.488353,36.614994],[-85.43640427288588,36.618003845027],[-85.29581248572748,36.62614955936749],[-85.290627,36.62645],[-85.27628794749938,36.62615754080338],[-85.096128,36.622483],[-84.97486843583738,36.61458335931719],[-84.943948,36.612569],[-84.78539997855027,36.603375419935595],[-84.785341,36.603372],[-84.77845586435048,36.60321051221589],[-84.499938,36.596678],[-84.26132120150467,36.592741697266995],[-84.227332,36.592181],[-84.22719396199828,36.59217951235509],[-83.987842,36.5896],[-83.98761095068278,36.58959228607249],[-83.93076078394387,36.58769425811239],[-83.894421,36.586481],[-83.690714,36.582581],[-83.675413,36.600814],[-83.47209357380957,36.59947573205929],[-83.2763,36.598187],[-82.98444890418119,36.59528987383889],[-82.830433,36.593761],[-82.60918194939899,36.5950896860685],[-82.487238,36.595822],[-82.29413642012908,36.595073032958496],[-82.24338500520017,36.59487618766539],[-82.173982,36.594607],[-82.14607026753038,36.594561147288594],[-81.934144,36.594213],[-81.922644,36.616213],[-81.82673414805258,36.614719104161395],[-81.6469,36.611918],[-81.677535,36.588117],[-81.699962,36.536829],[-81.695311,36.467912],[-81.734312,36.413342],[-81.72537277968526,36.38973849743609],[-81.705966,36.338496],[-81.768977,36.341042],[-81.833202,36.347339],[-81.908137,36.302013],[-81.91844447290477,36.287357917382096],[-81.93436924449257,36.264716204379795],[-81.960101,36.228131],[-82.02874,36.124322],[-82.080143,36.10572],[-82.08114891713238,36.105692114332584],[-82.127146,36.104417],[-82.140847,36.136216],[-82.211251,36.159012],[-82.22025301028657,36.15382003984309],[-82.26569,36.127614],[-82.297655,36.13351],[-82.346857,36.115209],[-82.409458,36.083409],[-82.41693759467316,36.07297001070849],[-82.464558,36.006508],[-82.50800765972248,35.98201320544148],[-82.557874,35.953901],[-82.610885,35.974442],[-82.595525,36.026012],[-82.60570361079358,36.03719886356189],[-82.628365,36.062105],[-82.725065,36.018204],[-82.779397,35.992511],[-82.787465,35.952163],[-82.81613,35.923986],[-82.860724,35.94743],[-82.89375141843136,35.93385726970889],[-82.910608,35.92693],[-82.899718,35.874602],[-82.937437,35.82732],[-82.96664974289857,35.795445979573984],[-82.978414,35.78261],[-83.04853,35.787706],[-83.097193,35.776067],[-83.161537,35.763363],[-83.198267,35.725494],[-83.255351,35.71623],[-83.25614155230359,35.715124062657786],[-83.26474416829,35.70308949617009],[-83.297154,35.65775],[-83.347262,35.660474],[-83.421576,35.611186],[-83.452431,35.602918],[-83.498335,35.562981],[-83.587827,35.566963],[-83.653159,35.568309],[-83.66291190158928,35.567799793208295],[-83.771736,35.562118],[-83.848502,35.519259],[-83.916801,35.473612],[-83.95323138015038,35.46002088957669],[-83.95891783456389,35.45789943957989],[-83.973171,35.452582],[-84.021782,35.407418],[-84.007586,35.371661],[-84.038081,35.348363],[-84.02351,35.295783],[-84.02910441377247,35.29212377649389],[-84.097508,35.247382],[-84.178516,35.240679],[-84.223718,35.269078],[-84.28322,35.226577],[-84.28659837874088,35.20575821849589],[-84.321869,34.988408],[-84.509052,34.988033],[-84.621483,34.988329],[-84.727434,34.98802],[-84.77583767129727,34.98793720614929],[-84.81047746688638,34.98787795522919],[-84.861314,34.987791],[-84.97697380659228,34.987219837354885],[-84.97985402523149,34.98720561397559],[-85.045183,34.986883],[-85.26505502171578,34.985077644741686],[-85.277556,34.984975],[-85.36391902893108,34.983376563140496],[-85.384967,34.982987],[-85.47433884313428,34.98367332679109],[-85.605165,34.984678],[-85.86394611180688,34.98703085874809],[-86.311274,34.991098],[-86.31876076546509,34.991078580442796],[-86.467798,34.990692],[-86.78362801716898,34.991924921991995],[-86.783648,34.991925],[-86.8362863159495,34.992803004216995],[-87.21075857998228,34.99904918099969],[-87.216683,34.999148],[-87.22405364187567,34.99923074197209],[-87.60609786765326,35.00351952620429],[-87.625025,35.003732],[-87.851886,35.005656],[-87.98491604369889,35.005910124325794],[-88.000032,35.005939],[-88.202959,35.008028],[-88.200064,34.995634],[-88.258111,34.995463],[-88.36353026853918,34.99574675179709],[-88.38049251152206,34.995792408222094],[-88.469877,34.996033],[-88.786612,34.995252],[-88.823050501632,34.995207045695],[-89.01712701155239,34.99496761283629],[-89.02654,34.994956],[-89.19828790149498,34.994450530115095],[-89.35267939184838,34.99399614174589],[-89.434954,34.993754],[-89.64428383409208,34.994067210562484],[-89.72431583796856,34.994186958753495],[-89.75961264223437,34.99423977173149],[-89.795187,34.994293],[-90.309297,34.995694],[-90.300697,35.028793]]]}}, {"type":"Feature","properties":{"name":"Texas","income":{"1995":31488,"1996":32773,"1997":34478,"1998":35449,"1999":38092,"2000":39090,"2001":40152,"2002":40063,"2003":39967,"2004":41645,"2005":42165,"2006":44943,"2007":47563,"2008":50049,"2009":48286,"2010":48622,"2011":49390,"2012":50747,"2013":51714,"2014":53067,"2015":55668}},"geometry":{"type":"Polygon","coordinates":[[[-106.623445,31.914034],[-106.630114,31.971258],[-106.618486,32.000495],[-106.37717318824697,32.00124010103749],[-106.200699,32.001785],[-105.99797115166398,32.00197459069899],[-105.750527,32.002206],[-105.153994,32.000497],[-104.91835699427997,32.000472073073496],[-104.84774,32.000464602834995],[-104.643526,32.000443],[-104.024521,32.00001],[-103.98021347738099,32.00003285136259],[-103.72288197914799,32.00016556867639],[-103.326501,32.00037],[-103.064423,32.000518],[-103.06442240110597,32.087051],[-103.064422,32.145006],[-103.064696,32.522193],[-103.064761,32.587983],[-103.064889,32.849359],[-103.06346888847497,32.959106381830495],[-103.060103,33.219225],[-103.056495064338,33.38841421462059],[-103.05261051656397,33.57057477644219],[-103.05261,33.570599],[-103.04734601816698,33.824674123151695],[-103.047346,33.824675],[-103.043516,34.079382],[-103.04356392079099,34.11283438975539],[-103.043835830165,34.302648],[-103.04385030117197,34.31274987350789],[-103.043946,34.379555],[-103.043072,34.619782],[-103.042769,34.747361],[-103.04273881860799,34.95414204036139],[-103.042711,35.144735],[-103.04261795056497,35.1831572590084],[-103.041554,35.622487],[-103.04155399893398,35.62248763195869],[-103.04135672181798,35.73943350634869],[-103.040824,36.055231],[-103.041924,36.500439],[-103.002434,36.500397],[-102.162463,36.500326],[-102.03233901896297,36.50006567301009],[-101.826565,36.499654],[-101.623915,36.499528],[-101.085156,36.499244],[-100.95415215769299,36.49952949662619],[-100.884174,36.499682],[-100.592614,36.499469],[-100.54614512609699,36.49950513930379],[-100.311018,36.499688],[-100.00376199336799,36.499701848737594],[-100.000406,36.499702],[-100.000399,36.055677],[-100.00039619832899,35.880947999996785],[-100.000392,35.619115],[-100.00038884414299,35.42236398830939],[-100.000385,35.182702],[-100.00038402077298,35.03038499999989],[-100.000382194816,34.74636055256159],[-100.000381,34.560509],[-99.99762932816299,34.56113662456009],[-99.929334,34.576714],[-99.84206388414638,34.50693276888139],[-99.818186,34.48784],[-99.764882,34.435266],[-99.696462,34.381036],[-99.600026,34.374688],[-99.58448,34.407673],[-99.47502213703837,34.39687098979049],[-99.470969,34.396471],[-99.420432,34.380464],[-99.394956,34.442099],[-99.350407,34.437083],[-99.27534,34.386599],[-99.22160790084548,34.32537357437259],[-99.2116,34.31397],[-99.189511,34.214312],[-99.131553,34.209352],[-99.0588,34.201256],[-99.002916,34.208782],[-98.95232488752816,34.20466989860349],[-98.94022,34.203686],[-98.872229,34.160446],[-98.80681,34.155901],[-98.737232,34.130992],[-98.690072,34.133155],[-98.648073,34.164441],[-98.61035178164467,34.15620993949669],[-98.577136,34.148962],[-98.5282,34.094961],[-98.475066,34.064269],[-98.423533,34.081949476005896],[-98.414426,34.085074],[-98.398441,34.128456],[-98.364023,34.157109],[-98.31875,34.146421],[-98.225282,34.127245],[-98.16912,34.114171],[-98.13848602574639,34.14120601971109],[-98.123377,34.15454],[-98.099328,34.104295],[-98.099096,34.048639],[-98.082839,34.002412],[-98.005667,33.995964],[-97.947572,33.991053],[-97.953695,33.924373],[-97.95190595085516,33.89122581485729],[-97.951215,33.878424],[-97.865765,33.849393],[-97.803473,33.88019],[-97.759834,33.92521],[-97.671772,33.99137],[-97.609091,33.968093],[-97.596155,33.922106],[-97.56124315022106,33.89906150673299],[-97.55827,33.897099],[-97.486505,33.916994],[-97.48414343858758,33.91388910889089],[-97.451469,33.87093],[-97.444193,33.823773],[-97.372941,33.819454],[-97.318243,33.865121],[-97.24618,33.900344],[-97.206141,33.91428],[-97.166629,33.847311],[-97.205652,33.809824],[-97.149394,33.721967],[-97.091072,33.735115],[-97.087852,33.774099],[-97.07859,33.812756],[-97.055838,33.855741],[-96.985567,33.886522],[-96.988745,33.918468],[-96.952313,33.944582],[-96.94461688837048,33.945013250454],[-96.93434330313298,33.94558892925279],[-96.905253,33.947219],[-96.897194,33.902954],[-96.850593,33.847211],[-96.794276,33.868886],[-96.776766,33.841976],[-96.712422,33.831633],[-96.682103,33.876645],[-96.659896,33.916666],[-96.59467430737708,33.883018657398296],[-96.590112,33.880665],[-96.592926,33.830916],[-96.572937,33.819098],[-96.523863,33.818114],[-96.502286,33.77346],[-96.436455,33.78005],[-96.403507,33.746289],[-96.37966082595207,33.715530908565995],[-96.363135,33.694215],[-96.307389,33.735005],[-96.277269,33.769735],[-96.229023,33.748021],[-96.173025,33.80056],[-96.15163,33.831946],[-96.063924,33.841523],[-95.935325,33.875099],[-95.887491,33.863856],[-95.84487853407067,33.86042190471899],[-95.820596,33.858465],[-95.78963931775226,33.87243738467229],[-95.737508,33.895967],[-95.669978,33.905844],[-95.603657,33.927195],[-95.556915,33.92702],[-95.525322,33.885487],[-95.44737,33.86885],[-95.352338,33.867789],[-95.31044979544906,33.87384303818549],[-95.283445,33.877746],[-95.253623,33.92971],[-95.226393,33.961954],[-95.15590761710747,33.93848238856979],[-95.149462,33.936336],[-95.095002,33.904816],[-95.046568,33.862565],[-94.98165,33.852284],[-94.93956,33.810503],[-94.902276,33.776289],[-94.841634,33.739431],[-94.766146,33.748031],[-94.73193290199589,33.720830516280294],[-94.714865,33.707261],[-94.630586,33.673401],[-94.572872,33.669886],[-94.528928,33.62184],[-94.485875,33.637867],[-94.419057,33.577217],[-94.388052,33.565511],[-94.354165,33.556452],[-94.338422,33.567082],[-94.303742,33.564486],[-94.238868,33.576722],[-94.213605,33.570622],[-94.183395,33.592212],[-94.143024,33.577725],[-94.07267,33.572234],[-94.04383374780107,33.551713735585594],[-94.043428,33.551425],[-94.042988,33.435824],[-94.043067,33.330498],[-94.04294584717597,33.27124208413979],[-94.042719,33.160291],[-94.042964,33.019219],[-94.04300262156329,32.88108897892399],[-94.043026,32.797476],[-94.04305152761756,32.69302997666559],[-94.043083,32.564261],[-94.0427882328053,32.392283193281195],[-94.042739,32.363559],[-94.04269592374007,32.196004974824895],[-94.042681,32.137956],[-94.041833,31.992402],[-94.02942840659598,31.979686964167996],[-93.977461,31.926419],[-93.909557,31.893144],[-93.87825189538658,31.844276557245585],[-93.85339,31.805467],[-93.803419,31.700686],[-93.816838,31.622509],[-93.834924,31.586211],[-93.83492321447775,31.586210021077996],[-93.787687,31.527344],[-93.725925,31.504092],[-93.749476,31.46869],[-93.697603,31.428409],[-93.668146,31.375103],[-93.67544,31.30104],[-93.613942,31.259375],[-93.602443,31.182541],[-93.60060308736288,31.18262495526879],[-93.55249730750228,31.18482002344679],[-93.535097,31.185614],[-93.540278,31.128868],[-93.531219,31.051678],[-93.539526,31.008498],[-93.549841,30.967118],[-93.530936,30.924534],[-93.55457585434549,30.87746950186109],[-93.558617,30.869424],[-93.569303,30.802969],[-93.617688,30.738479],[-93.629904,30.67994],[-93.685121,30.625201],[-93.684329,30.592586],[-93.729195,30.544842],[-93.710117,30.5064],[-93.702665,30.429947],[-93.738540238226,30.40226367248079],[-93.745333,30.397022],[-93.760328,30.329924],[-93.70719,30.275513],[-93.71106217130087,30.24397071564029],[-93.713359,30.225261],[-93.703764,30.173936],[-93.702436,30.112721],[-93.70394,30.054291],[-93.70633576247016,30.05218024153089],[-93.741078,30.021571],[-93.807815,29.954549],[-93.830374,29.894359],[-93.85230987092228,29.87209100439189],[-93.872446,29.85165],[-93.929208,29.802952],[-93.890821,29.761673],[-93.863204,29.724059],[-93.837971,29.690619],[-93.861291,29.679007],[-93.961867,29.682213],[-94.056506,29.671163],[-94.161549,29.636588],[-94.35412254491366,29.56210282017479],[-94.370816,29.555645988294994],[-94.48567951355406,29.51121813364729],[-94.500807,29.505367],[-94.594853,29.467903],[-94.670389,29.43078],[-94.731047,29.369141],[-94.72253,29.331446],[-94.803695,29.279237],[-95.026219,29.148064],[-95.11505050559828,29.075552022478696],[-95.125134,29.067321],[-95.191391,29.02309],[-95.297147,28.934073],[-95.38239,28.866348],[-95.439594,28.859022],[-95.50703739691699,28.824735512192095],[-95.588801,28.783169],[-95.684089,28.734041],[-95.812504,28.664942],[-96.000682,28.588238],[-96.194412,28.502224],[-96.328817,28.423659],[-96.37853315928677,28.389865030487893],[-96.390376,28.381815],[-96.442849,28.317666],[-96.63201,28.222821],[-96.719627,28.164594],[-96.792158,28.110497],[-96.85207062273007,28.059820861604592],[-96.886459,28.030734],[-97.003325,27.908307],[-97.04368408368649,27.836532353471792],[-97.044846,27.834466],[-97.090735,27.785888],[-97.140854,27.716688],[-97.212679,27.59642],[-97.22299140753177,27.576607316479592],[-97.257325,27.510644],[-97.296057,27.427175],[-97.336122,27.317818],[-97.34685087695567,27.277958832209496],[-97.358469,27.234796],[-97.378697,27.060044],[-97.366872,26.885581],[-97.32275,26.701746],[-97.28754111668576,26.600339881473296],[-97.253801,26.503164],[-97.22738022652179,26.411496005302496],[-97.196935,26.305865],[-97.158798,26.08266],[-97.151922,26.017653],[-97.145567,25.971132],[-97.156608,25.949022],[-97.206945,25.960899],[-97.277163,25.935438],[-97.338346,25.923125],[-97.365976,25.902447],[-97.360082,25.868874],[-97.372864,25.840117],[-97.422636,25.840378],[-97.454727,25.879337],[-97.496861,25.880058],[-97.542957,25.920035],[-97.582565,25.937857],[-97.644011,26.006614],[-97.697069,26.023455],[-97.758838,26.032131],[-97.795291,26.055218],[-97.86228156310628,26.05774682844019],[-97.871187,26.058083],[-97.944345,26.059621],[-98.010971,26.063863],[-98.039239,26.041275],[-98.091038,26.059169],[-98.149463,26.055813],[-98.197046,26.056153],[-98.20495395559236,26.058742336000396],[-98.248806,26.073101],[-98.302979,26.11005],[-98.30820011704587,26.11303255102869],[-98.386694,26.157872],[-98.442536,26.199151],[-98.503492,26.214798],[-98.576188,26.235221],[-98.59330021827917,26.242936348676594],[-98.613465,26.252028],[-98.654221,26.23596],[-98.698856,26.265619],[-98.779912,26.326542],[-98.807348,26.369421],[-98.890965,26.357569],[-98.958325,26.394056],[-99.032316,26.412082],[-99.082002,26.39651],[-99.110855,26.426278],[-99.091635,26.476977],[-99.105031,26.500335],[-99.171404,26.549848],[-99.17681609238107,26.56966055537359],[-99.200522,26.656443],[-99.208907,26.724761],[-99.242444,26.788262],[-99.268613,26.843213],[-99.3289,26.879761],[-99.361144,26.928921],[-99.387367,26.982399],[-99.44697,27.026026],[-99.442123,27.106839],[-99.429984,27.159149],[-99.445238,27.223341],[-99.46082579913427,27.262240197042793],[-99.463309,27.268437],[-99.487937,27.294941],[-99.529654,27.306051],[-99.487521,27.412396],[-99.495104,27.451518],[-99.497519,27.500496],[-99.52832,27.498896],[-99.530138,27.580207],[-99.556812,27.614336],[-99.624515,27.634515],[-99.704601,27.654954],[-99.758534,27.717071],[-99.801651,27.741771],[-99.844737,27.778809],[-99.87784,27.824376],[-99.904385,27.875284],[-99.917461,27.917973],[-99.932161,27.96771],[-99.984923,27.990729],[-100.028725,28.073118],[-100.075474,28.124882],[-100.174413,28.179448],[-100.19751005550097,28.19700073113989],[-100.267604,28.250269],[-100.287554,28.301093],[-100.320393,28.362117],[-100.337059,28.427151],[-100.368288,28.477196],[-100.38886,28.515748],[-100.39727,28.575637],[-100.448648,28.616774],[-100.500354,28.66196],[-100.506701,28.716745],[-100.533017,28.76328],[-100.53583,28.805888],[-100.576846,28.836168],[-100.627206,28.903734],[-100.646993,28.957079],[-100.660208,29.031497],[-100.67121518919397,29.08351602534449],[-100.674656,29.099777],[-100.727462,29.129123],[-100.772649,29.168492],[-100.795681,29.22773],[-100.80186754602899,29.232831568097993],[-100.848664,29.271421],[-100.886842,29.307848],[-100.995607,29.363403],[-101.060151,29.458661],[-101.137503,29.473542],[-101.19272,29.520285],[-101.254895,29.520342],[-101.305533,29.577925],[-101.307332,29.640716],[-101.367198,29.664041],[-101.400636,29.738079],[-101.453499,29.759671],[-101.503223,29.764582],[-101.561569,29.794658],[-101.654578,29.765163],[-101.714224,29.76766],[-101.76161920952798,29.778860096722187],[-101.809441,29.790161],[-101.8754,29.794023],[-101.966167,29.807343],[-102.021919,29.802491],[-102.073646,29.786926],[-102.115682,29.79239],[-102.161674,29.819487],[-102.227553,29.843534],[-102.301381,29.877674],[-102.31868395458798,29.872192946501492],[-102.349861,29.862317],[-102.369522,29.820395],[-102.392906,29.765569],[-102.468946,29.779817],[-102.512687,29.780303],[-102.551081,29.752358],[-102.612879,29.748182],[-102.677192,29.738261],[-102.693466,29.676507],[-102.738428,29.621929],[-102.777531,29.556497],[-102.808692,29.522319],[-102.83097,29.444267],[-102.824564,29.399558],[-102.871857,29.352093],[-102.891022,29.287113],[-102.871347,29.241625],[-102.917805,29.190697],[-102.995688,29.161219],[-103.035683,29.103029],[-103.076355,29.085722],[-103.100368,29.026877],[-103.126748,28.982124],[-103.227801,28.991532],[-103.28119,28.982138],[-103.361998,29.018914],[-103.463196,29.066822],[-103.524613,29.120998],[-103.59236,29.15026],[-103.660203,29.170934],[-103.724743,29.19147],[-103.789034,29.257502],[-103.79387301093399,29.259238393348593],[-103.856893,29.281852],[-103.975235,29.296017],[-104.055596,29.33091],[-104.143692,29.383278],[-104.181273,29.426265],[-104.229081,29.48105],[-104.308813,29.524337],[-104.371175,29.543063],[-104.452301,29.60366],[-104.539761,29.676074],[-104.565688,29.770462],[-104.619039,29.844445],[-104.672327,29.911112],[-104.685479,29.989943],[-104.703998,30.02421],[-104.692094,30.107304],[-104.702788,30.211736],[-104.740448,30.259454],[-104.761634,30.301148],[-104.824314,30.370466],[-104.859521,30.390413],[-104.869872,30.458645],[-104.889376,30.535144],[-104.924796,30.604832],[-104.972071,30.61026],[-104.98075389132498,30.62881201878829],[-105.00124,30.672583],[-105.062334,30.686303],[-105.098282,30.718914],[-105.160153,30.757059],[-105.21866,30.801567],[-105.314863,30.816961],[-105.394242,30.852979],[-105.399609,30.888941],[-105.488027,30.943278],[-105.55743,30.990229],[-105.579542,31.035396],[-105.627349,31.098545],[-105.709491,31.136375],[-105.773257,31.166897],[-105.794386,31.20224],[-105.869353,31.288634],[-105.938452,31.318735],[-105.953943,31.364749],[-105.99642937828698,31.38784012951259],[-106.004926,31.392458],[-106.080258,31.398702],[-106.175675,31.456279],[-106.236804,31.513376],[-106.280811,31.562062],[-106.303536,31.620413],[-106.35261099849798,31.686946416503595],[-106.370139,31.71071],[-106.41794,31.752009],[-106.467642,31.759608],[-106.484642,31.747809],[-106.528242,31.783148],[-106.581344,31.813906],[-106.63588,31.871514],[-106.623445,31.914034]]]}}, {"type":"Feature","properties":{"name":"Virginia","income":{"1995":36367,"1996":38510,"1997":40209,"1998":42622,"1999":44848,"2000":46789,"2001":48130,"2002":48224,"2003":50028,"2004":51103,"2005":54207,"2006":56297,"2007":59575,"2008":61210,"2009":59372,"2010":60665,"2011":61877,"2012":61782,"2013":62745,"2014":64923,"2015":66263}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-76.023475,37.289067],[-75.987122,37.368548],[-75.976491,37.444878],[-75.94557431893068,37.54904065815169],[-75.941182,37.563839],[-75.898665,37.635425],[-75.859262,37.703111],[-75.812155,37.749502],[-75.818125,37.791698],[-75.73588,37.816561],[-75.702914,37.849659],[-75.757694,37.903912],[-75.669711,37.950796],[-75.624341,37.994211],[-75.242266,38.027209],[-75.338623,37.894986],[-75.380638,37.851702],[-75.439001,37.869335],[-75.48927,37.832457],[-75.551898,37.748122],[-75.591953,37.663178],[-75.614527,37.609296],[-75.607824,37.560706],[-75.672877,37.483696],[-75.66541791087508,37.46729351549249],[-75.658379,37.451815],[-75.720739,37.373129],[-75.735829,37.335426],[-75.778817,37.297176],[-75.795164,37.247095],[-75.817387,37.193437],[-75.897298,37.118037],[-75.942399,37.089607],[-75.979608,37.100448],[-75.998647,37.188739],[-76.023475,37.289067]]],[[[-83.614513,36.633983],[-83.527112,36.665985],[-83.46095464746378,36.66613103627329],[-83.436508,36.666185],[-83.386099,36.686589],[-83.236399,36.726887],[-83.136395,36.743088],[-83.114693,36.796088],[-83.07559,36.850589],[-83.012587,36.847289],[-82.895445,36.882145],[-82.88361015487978,36.897314788915786],[-82.865192,36.920923],[-82.869183,36.974182],[-82.815748,37.007196],[-82.750715,37.024107],[-82.722254,37.057948],[-82.726294,37.111852],[-82.565275702797,37.19590110688309],[-82.558178,37.199606],[-82.55363382627456,37.20145269844589],[-82.449164,37.243908],[-82.355343,37.26522],[-82.31478127133458,37.29599456011749],[-82.309415,37.300066],[-82.201745,37.375108],[-81.968297,37.537798],[-81.932279,37.511961],[-81.984891,37.454315],[-81.93695,37.41992],[-81.933601,37.389217],[-81.896001,37.331967],[-81.849949,37.285227],[-81.774747,37.274847],[-81.744003,37.242528],[-81.73905503048546,37.23949710387279],[-81.678603,37.202467],[-81.560625,37.206663],[-81.53307,37.223414],[-81.483559,37.250604],[-81.427946,37.271015],[-81.362156,37.337687],[-81.225104,37.234874],[-81.112596,37.278497],[-80.996013,37.299545],[-80.98084525689279,37.30085281619049],[-80.919259,37.306163],[-80.835479,37.334824],[-80.883248,37.383933],[-80.865148,37.419927],[-80.85814811681978,37.421006906721495],[-80.85735857018977,37.421128713998996],[-80.836446,37.424355],[-80.770082,37.372363],[-80.664971,37.414215],[-80.544836,37.474695],[-80.47128294938639,37.43006549889589],[-80.46482,37.426144],[-80.39988,37.462314],[-80.291644,37.536505],[-80.28244,37.585481],[-80.223386,37.623185],[-80.22430324437678,37.62399137117089],[-80.292258,37.683732],[-80.290033810255,37.686136458971],[-80.258143,37.720612],[-80.218616,37.783291],[-80.199633,37.827507],[-80.131931,37.8895],[-80.05581159458966,37.951878220097896],[-80.036236,37.96792],[-79.971231,38.044326],[-79.96198227263537,38.06360709949329],[-79.938952,38.111619],[-79.916174,38.184386],[-79.850324,38.233329],[-79.79701353680687,38.267268121139196],[-79.787542,38.273298],[-79.804093,38.313922],[-79.7346,38.356728],[-79.689675,38.431439],[-79.691088,38.463744],[-79.669128,38.510883],[-79.649075,38.591515],[-79.54257,38.553217],[-79.476638,38.457228],[-79.370302,38.427244],[-79.31129606551438,38.41845460145499],[-79.297758,38.416438],[-79.23162,38.474041],[-79.22825588138187,38.48003955108519],[-79.201459,38.527821],[-79.154357,38.606518],[-79.092955,38.659517],[-79.088055,38.690115],[-79.057253,38.761413],[-79.023053,38.798613],[-78.999014,38.840074],[-78.869276,38.762991],[-78.821167,38.830982],[-78.772793,38.893742],[-78.681617,38.92584],[-78.620453,38.982601],[-78.561711,39.009007],[-78.53214700369618,39.05294164002129],[-78.508132,39.08863],[-78.413943,39.158415],[-78.428697,39.187217],[-78.40498,39.238006],[-78.401813,39.276754],[-78.34048,39.353492],[-78.337133,39.409169],[-78.347087,39.466012],[-78.22912953421849,39.39066388720409],[-78.18737,39.363989],[-78.03318523536657,39.26462484200518],[-78.03318346093418,39.26462369847469],[-78.032841,39.264403],[-77.82830183326728,39.132422454832486],[-77.828157,39.132329],[-77.809125,39.168567],[-77.778068,39.229305],[-77.719519,39.321314],[-77.67769576207868,39.317940817087994],[-77.66613,39.317008],[-77.588235,39.301955],[-77.553114,39.279268],[-77.496606,39.251045],[-77.46006562649778,39.218842943859386],[-77.459883,39.218682],[-77.485971,39.185665],[-77.521222,39.161057],[-77.519929,39.120925],[-77.481279,39.105658],[-77.462617,39.076248],[-77.359702,39.062004],[-77.33003770595407,39.055952113490996],[-77.310705,39.052008],[-77.248403,39.026909],[-77.24840370497539,39.02688835429229],[-77.249803,38.985909],[-77.202502,38.96791],[-77.146601,38.96421],[-77.119759,38.934343],[-77.0902,38.904211],[-77.039099,38.868112],[-77.03906635676466,38.841271889518595],[-77.039006,38.791645],[-77.03923988508228,38.78533632562359],[-77.04067257077807,38.74669193048289],[-77.040998,38.737914],[-77.053199,38.709915],[-77.079499,38.709515],[-77.08578476515638,38.70528128183239],[-77.132501,38.673816],[-77.1302,38.635017],[-77.22414585530147,38.63517827490088],[-77.246704,38.635217],[-77.295274,38.562125],[-77.29923201266608,38.54837673851089],[-77.31290355402578,38.50088827866289],[-77.322622,38.467131],[-77.317288,38.383576],[-77.28299760033909,38.350328960258],[-77.265295,38.333165],[-77.162692,38.345994],[-77.093713,38.352801],[-77.048137,38.360145],[-77.020947,38.329273],[-77.026304,38.302685],[-76.99679125920488,38.27914783397989],[-76.990255,38.273935],[-76.957796,38.243183],[-76.962311,38.214075],[-76.910832,38.197073],[-76.838795,38.163476],[-76.749685,38.162114],[-76.684892,38.156497],[-76.613939,38.148587],[-76.600937,38.110084],[-76.535919,38.069532],[-76.51069396131767,38.03948892781419],[-76.491998,38.017222],[-76.427487,37.977038],[-76.316952,37.934929],[-76.236725,37.889174],[-76.251358,37.833072],[-76.310307,37.794849],[-76.312858,37.720338],[-76.3252991496906,37.68257388543669],[-76.32912,37.670976],[-76.279447,37.618225],[-76.28887783670189,37.587359934103986],[-76.29796,37.557636],[-76.28949279717807,37.53607528800879],[-76.273488,37.495321],[-76.250454,37.421886],[-76.24846,37.375135],[-76.275552,37.309964],[-76.366751,37.374495],[-76.393958,37.39594],[-76.40294587535288,37.392600001791195],[-76.437525,37.37975],[-76.38777,37.30767],[-76.36229,37.270226],[-76.37693680971749,37.24949176236329],[-76.394132,37.22515],[-76.34718992896758,37.189644493655294],[-76.3431,37.186551],[-76.311088,37.138495],[-76.293126918301,37.11416370088029],[-76.271262,37.084544],[-76.28388890538098,37.052731542777394],[-76.304272,37.001378],[-76.29679229029519,36.99379096645169],[-76.28097205081657,36.97774372766799],[-76.267962,36.964547],[-76.189959,36.931447],[-76.17694758519868,36.92853868015499],[-76.087955,36.908647],[-76.043054,36.927547],[-75.996252,36.922047],[-75.961589,36.799995],[-75.921748,36.692051],[-75.890946,36.630753],[-75.867044,36.550754],[-76.02675,36.550553],[-76.12234994701008,36.55055233255409],[-76.313215,36.550551],[-76.31330296826026,36.550551089806994],[-76.49148257547228,36.55073299383639],[-76.54196586571828,36.55078453236009],[-76.738329,36.550985],[-76.91573180234968,36.546089769338884],[-76.91603763285619,36.54608133029029],[-76.917318,36.546046],[-77.16432273355687,36.546152819904094],[-77.190175,36.546164],[-77.29877018881177,36.546039010854486],[-77.749706,36.54552],[-77.76710333422477,36.545442412170495],[-77.89977414050628,36.54485073302249],[-78.04620830436028,36.54419767268659],[-78.132911,36.543811],[-78.32371850955899,36.54242139155859],[-78.45727789625586,36.541448708399486],[-78.509965,36.541065],[-78.73412280111718,36.54160873484079],[-78.79627395514048,36.541759493581594],[-78.942009,36.542113],[-79.13833589887138,36.54163827005589],[-79.21845549592226,36.541444536176094],[-79.3428439209599,36.54114375767659],[-79.47005667392429,36.54083614978659],[-79.510647,36.540738],[-79.51364766250857,36.54074820507069],[-79.71485081105197,36.54143248474129],[-79.89167016695387,36.54203383661619],[-80.027269,36.542495],[-80.02733891514119,36.54249538561418],[-80.05345504335008,36.542639428086595],[-80.295243,36.543973],[-80.431605,36.550219],[-80.44006854346448,36.550593813802195],[-80.61218878812458,36.55821627638039],[-80.704831,36.562319],[-80.84021307724598,36.56192845163729],[-80.90166111892098,36.56175118716799],[-80.901726,36.561751],[-81.061866,36.56702],[-81.176712,36.571926],[-81.35322122460218,36.57623823115639],[-81.499831,36.57982],[-81.677535,36.588117],[-81.6469,36.611918],[-81.82673414805258,36.614719104161395],[-81.922644,36.616213],[-81.934144,36.594213],[-82.14607026753038,36.594561147288594],[-82.173982,36.594607],[-82.24338500520017,36.59487618766539],[-82.29413642012908,36.595073032958496],[-82.487238,36.595822],[-82.60918194939899,36.5950896860685],[-82.830433,36.593761],[-82.98444890418119,36.59528987383889],[-83.2763,36.598187],[-83.47209357380957,36.59947573205929],[-83.675413,36.600814],[-83.614513,36.633983]]]]}}, {"type":"Feature","properties":{"name":"Wisconsin","income":{"1995":37572,"1996":38598,"1997":39800,"1998":42169,"1999":43301,"2000":44503,"2001":45435,"2002":45377,"2003":46538,"2004":46142,"2005":47141,"2006":48784,"2007":50567,"2008":52103,"2009":49994,"2010":48974,"2011":50401,"2012":51063,"2013":51474,"2014":52632,"2015":55623}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-86.934276,45.421149],[-86.835749,45.450188],[-86.805868,45.412903],[-86.867743,45.353065],[-86.899891,45.295185],[-86.956198,45.352006],[-86.934276,45.421149]]],[[[-90.776921,47.024324],[-90.74018,47.036105],[-90.650422,47.054678],[-90.560936,47.037013],[-90.544875,47.017383],[-90.511623,46.961407],[-90.524056,46.935664],[-90.549104,46.915461],[-90.637124,46.906724],[-90.679446,46.956032],[-90.712032,46.98526],[-90.767985,47.002327],[-90.776921,47.024324]]],[[[-92.88669712440898,45.644148],[-92.869689,45.715142],[-92.84074210662547,45.72939673446969],[-92.826013,45.73665],[-92.776496,45.790014],[-92.759458,45.835341],[-92.721128,45.883805],[-92.656125,45.924442],[-92.580565,45.94625],[-92.545682,45.970118],[-92.472761,45.972952],[-92.44963,46.002252],[-92.392681,46.01954],[-92.35176,46.015685],[-92.338239,46.052149],[-92.294033,46.074377],[-92.29383060857869,46.157321306495994],[-92.293619,46.244043],[-92.29275980242826,46.417219502879995],[-92.292371,46.495585],[-92.292192,46.663242],[-92.205492,46.664741],[-92.183091,46.695241],[-92.143338,46.731596],[-92.100255,46.734446],[-92.050819,46.710517],[-92.01529,46.706469],[-91.961889,46.682539],[-91.886963,46.690211],[-91.820027,46.690176],[-91.645502,46.734733],[-91.574291,46.757488],[-91.55134153565636,46.75747529345949],[-91.511077,46.757453],[-91.411799,46.78964],[-91.360804,46.798136],[-91.314815,46.826825],[-91.256705,46.836887],[-91.211647,46.866824],[-91.167601,46.84476],[-91.130475,46.870008],[-91.087357,46.879471],[-91.034518,46.903053],[-90.984617,46.925602],[-90.989375,46.982274],[-90.924128,47.001888],[-90.85284,46.962558],[-90.80628,46.938738],[-90.745305,46.894254],[-90.798936,46.823143],[-90.861046,46.765631],[-90.880841,46.739957],[-90.852704,46.699582],[-90.915152,46.65841],[-90.932626,46.617296],[-90.95565,46.592503],[-90.92522939534257,46.587488072445595],[-90.898308,46.58305],[-90.829031,46.616066],[-90.794775,46.624941],[-90.755287,46.646289],[-90.73726,46.692267],[-90.663273,46.645326],[-90.56556,46.584892],[-90.54857855596607,46.58623625875048],[-90.505909,46.589614],[-90.437596,46.561492],[-90.418136,46.566094],[-90.387228,46.533663],[-90.331887,46.553278],[-90.285707,46.518846],[-90.214866,46.499947],[-90.158241,46.420485],[-90.120489,46.336852],[-89.92912562566477,46.29991572840809],[-89.638416,46.243804],[-89.09163,46.138505],[-88.99121702839598,46.09653635443599],[-88.93276845100957,46.07210716377599],[-88.811948,46.021609],[-88.739994,46.027308],[-88.68323220849936,46.014465670320284],[-88.679132,46.013538],[-88.65776,45.989287],[-88.613063,45.990627],[-88.59386,46.015132],[-88.526673,46.020822],[-88.409864,45.979688],[-88.380183,45.991654],[-88.30952,45.959369],[-88.246307,45.962983],[-88.178008,45.947111],[-88.11685653737608,45.92281124226269],[-88.115346,45.922211],[-88.073944,45.875593],[-88.135067,45.821694],[-88.105518,45.798839],[-88.05701046594899,45.784977030143686],[-88.048514,45.782549],[-87.995876,45.795435],[-87.96697,45.764021],[-87.879812,45.754843],[-87.83304946803528,45.72275257534689],[-87.805076,45.703556],[-87.781007,45.673934],[-87.824676,45.653211],[-87.777671,45.609204],[-87.787292,45.574906],[-87.804203,45.524676],[-87.805773,45.473139],[-87.847429,45.444177],[-87.85683,45.393106],[-87.863489,45.35302],[-87.800464,45.353608],[-87.750928,45.355037],[-87.706767,45.383827],[-87.657349,45.368752],[-87.667423,45.31636],[-87.71148,45.245224],[-87.741805,45.197051],[-87.695055,45.150522],[-87.648191,45.106368],[-87.590208,45.095264],[-87.625748,45.045157],[-87.630298,44.976865],[-87.696492,44.974233],[-87.76263849097109,44.962752171760286],[-87.812989,44.954013],[-87.843433,44.924355],[-87.838359,44.873987],[-87.854681,44.857771],[-87.904484,44.818723],[-87.941453,44.75608],[-87.983494,44.720196],[-87.99757340644248,44.677663939044784],[-88.002085,44.664035],[-87.998716,44.609288],[-88.041202,44.572581],[-88.005518,44.539216],[-87.943801,44.529693],[-87.898888,44.574135],[-87.866884,44.608434],[-87.77516,44.639281],[-87.76130767888509,44.653697749734896],[-87.748409,44.667122],[-87.73757086086626,44.67701181615589],[-87.71978,44.693246],[-87.720889,44.724548],[-87.6463,44.798739],[-87.581306,44.851791],[-87.530999,44.857437],[-87.515142,44.869596],[-87.446477,44.886109],[-87.393405,44.934393],[-87.336457,45.01353],[-87.264877,45.081361],[-87.238224,45.167259],[-87.175068,45.17305],[-87.121609,45.209783],[-87.108743,45.257003],[-87.057627,45.292838],[-87.017036,45.299254],[-86.97778,45.290684],[-86.978759,45.227333],[-87.04417,45.186946],[-87.045748,45.134987],[-87.063157,45.079316],[-87.139384,45.012565],[-87.188375,44.948077],[-87.206285,44.885928],[-87.27603,44.83318],[-87.318982,44.771335],[-87.37549155021938,44.67551210980499],[-87.401629,44.631191],[-87.446963,44.586274],[-87.498662,44.460686],[-87.54332678547608,44.32751285612989],[-87.545382,44.321385],[-87.521755,44.259957],[-87.507419,44.210803],[-87.53994,44.15969],[-87.600882,44.131695],[-87.655183,44.081894],[-87.69892,43.965936],[-87.72857954230886,43.89220888745679],[-87.736017,43.873721],[-87.726407,43.810445],[-87.700251,43.76735],[-87.708185,43.722895],[-87.706204,43.679542],[-87.790135,43.563054],[-87.79102015567156,43.54301509078658],[-87.793239,43.492783],[-87.840955,43.420677],[-87.889207,43.307652],[-87.896286,43.197108],[-87.89657933386819,43.19213424797579],[-87.900485,43.12591],[-87.870184,43.064412],[-87.895784,43.015814],[-87.842681,42.944116],[-87.834879,42.856717],[-87.83136496100246,42.853016604204385],[-87.82116293803398,42.842273546735385],[-87.766675,42.784896],[-87.785074,42.700819],[-87.80201505510958,42.66831106117669],[-87.814674,42.64402],[-87.813273,42.57922],[-87.800477,42.49192],[-87.89770179730027,42.49285460462939],[-88.19952900144847,42.49575601569028],[-88.2169,42.495923],[-88.304692,42.49560817275149],[-88.506912,42.494883],[-88.70737771540178,42.49358701476958],[-88.70738,42.493587],[-88.77649576073519,42.494136600467385],[-88.94038486037799,42.49543982747118],[-88.99256022681729,42.495854719899185],[-89.042898,42.496255],[-89.36579860766348,42.50002596695148],[-89.40141681104056,42.50044193107369],[-89.493216,42.501514],[-89.83759488632558,42.50491035279149],[-89.926484,42.505787],[-89.927006876764,42.50579048577459],[-90.22319,42.507765],[-90.42637696073606,42.50717773522369],[-90.437011,42.507147],[-90.642843,42.508481],[-90.672727,42.576599],[-90.700856,42.626445],[-90.743677,42.64556],[-90.852497,42.664822],[-90.89696202715838,42.674318056434295],[-90.941567,42.683844],[-91.017239,42.719566],[-91.070716,42.775502],[-91.09882,42.864421],[-91.138,42.903772],[-91.155519,42.975774],[-91.15908430594746,42.98747779132278],[-91.174692,43.038713],[-91.17493491391117,43.08026037184519],[-91.175253,43.134665],[-91.134173,43.174405],[-91.087456,43.221891],[-91.05791,43.253968],[-91.107237,43.313645],[-91.154806,43.334826],[-91.207367,43.373659],[-91.199408,43.403032],[-91.21066335777269,43.41944178290329],[-91.232276,43.450952],[-91.217706,43.50055],[-91.232812,43.564842],[-91.252926,43.600363],[-91.273252,43.666623],[-91.25700015600567,43.72565873722238],[-91.243955,43.773046],[-91.28765562736709,43.847065],[-91.291002,43.852733],[-91.357426,43.917231],[-91.42356869981727,43.984296880322596],[-91.440536,44.001501],[-91.55921556303969,44.024209316581185],[-91.573283,44.026901],[-91.647873,44.064109],[-91.719097,44.128853],[-91.817302,44.164235],[-91.85449997529766,44.197226519552196],[-91.892698,44.231105],[-91.916191,44.318094],[-91.9636,44.362112],[-92.08452858049277,44.404614314800995],[-92.111085,44.413948],[-92.232472,44.445434],[-92.24536464900538,44.454251124351785],[-92.291005,44.485464],[-92.314071,44.538014],[-92.31693313340578,44.539276012202684],[-92.361518,44.558935],[-92.399281,44.558292],[-92.54928,44.577704],[-92.618025,44.61287],[-92.696491,44.689436],[-92.73162385130317,44.71492278525959],[-92.79236079967048,44.758983813697085],[-92.805287,44.768361],[-92.768574,44.854368],[-92.76711733435718,44.86151518587589],[-92.76702326575186,44.861976737097685],[-92.750802,44.941567],[-92.761904,45.022467],[-92.802911,45.065403],[-92.740509,45.113396],[-92.74382347936557,45.123646262323],[-92.766932,45.195111],[-92.76609140867366,45.210021702422694],[-92.761868,45.284938],[-92.74826767468588,45.29605938650979],[-92.698967,45.336374],[-92.658486,45.396058],[-92.646768,45.437929],[-92.686793,45.472271],[-92.728023,45.525652],[-92.756906,45.557499],[-92.801503,45.562854],[-92.881136,45.573409],[-92.887929,45.639006],[-92.88669712440898,45.644148]]]]}}, {"type":"Feature","properties":{"name":"South Dakota","income":{"1995":29426,"1996":29810,"1997":31354,"1998":33267,"1999":35007,"2000":36146,"2001":37096,"2002":36966,"2003":38008,"2004":39265,"2005":40096,"2006":42432,"2007":43507,"2008":46244,"2009":45048,"2010":45861,"2011":48188,"2012":48439,"2013":49200,"2014":51059,"2015":53263}},"geometry":{"type":"Polygon","coordinates":[[[-104.057698,44.997431],[-104.039138,44.99852],[-104.039977,45.124988],[-104.04013575649299,45.21289076204159],[-104.040358,45.335946],[-104.041764,45.490789],[-104.041937,45.557915],[-104.042597,45.749998],[-104.043776,45.864707],[-104.04413315610697,45.88197625834978],[-104.045443,45.94531],[-103.660779,45.945241],[-103.434851,45.945291],[-103.218396,45.945208],[-102.99566801913798,45.94511644377148],[-102.94206996119098,45.94509441135319],[-102.880252,45.945069],[-102.704871,45.945072],[-102.550947,45.945015],[-102.32823,45.944806],[-102.087555,45.944598],[-102.00067992101798,45.944538392727495],[-101.99861707823398,45.94453697735689],[-101.794606,45.944397],[-101.557276,45.9441],[-101.365283,45.944092],[-101.106826,45.943984],[-100.76211,45.943767],[-100.511949026151,45.943654070434484],[-100.511793,45.943654],[-100.49935421538399,45.94363199881429],[-100.294126,45.943269],[-100.152084,45.942486],[-99.880292,45.941672],[-99.88006209480658,45.94167091580218],[-99.718073,45.940907],[-99.71807104288217,45.94090700349639],[-99.61116,45.941098],[-99.490254,45.940362],[-99.34496,45.940299],[-99.092868,45.940184],[-99.00575435015247,45.93994430912839],[-99.005642,45.939944],[-98.72437441388807,45.93867473326149],[-98.625379,45.938228],[-98.414518,45.936504],[-98.070515,45.93618],[-98.00810179827778,45.936012629049294],[-97.97877780962337,45.93593399209868],[-97.77704,45.935393],[-97.542598,45.935258],[-97.228291,45.93565659564609],[-97.082093,45.935842],[-96.563672,45.935245],[-96.571871,45.871846],[-96.587093,45.816445],[-96.630512,45.781157],[-96.672665,45.732336],[-96.745086,45.701576],[-96.82616,45.654164],[-96.851621,45.619412],[-96.843957,45.594003],[-96.83541916197808,45.58612869288079],[-96.781036,45.535972],[-96.742509,45.478723],[-96.710786,45.43693],[-96.675447,45.410216],[-96.617726,45.408092],[-96.562142,45.38609],[-96.521787,45.375645],[-96.482556,45.346273],[-96.47007760304926,45.32679964939229],[-96.457781,45.30761],[-96.45755349848498,45.26889792871839],[-96.45584011363358,44.97734524827999],[-96.45483051555378,44.80555020404578],[-96.45380669966707,44.63133583194799],[-96.45329131359868,44.543636801817996],[-96.452213,44.360149],[-96.45243582459547,44.196801586664996],[-96.45243585466946,44.19677954009509],[-96.45290957169317,43.849508852637186],[-96.45290957436626,43.84950689301839],[-96.453315,43.552299],[-96.45326,43.50039],[-96.598928,43.500457],[-96.584603,43.46961],[-96.594254,43.434153],[-96.521572,43.38564],[-96.524289,43.347214],[-96.530392,43.300034],[-96.578823,43.291095],[-96.55902734270967,43.257555675617986],[-96.552963,43.247281],[-96.522084,43.22096],[-96.475571,43.221054],[-96.458854,43.143356],[-96.439335,43.113916],[-96.45209751605368,43.082552925194484],[-96.458201,43.067554],[-96.511605,43.039927],[-96.492693,43.005089],[-96.520246,42.977643],[-96.500308,42.959391],[-96.541689,42.922576],[-96.54047232919328,42.90859569795599],[-96.537851,42.878475],[-96.577937,42.827645],[-96.621875,42.779255],[-96.624704,42.725497],[-96.591602,42.688081],[-96.526766,42.641184],[-96.48002247897999,42.56132477656069],[-96.476952,42.556079],[-96.49297,42.517282],[-96.477454,42.509589],[-96.445508,42.49063],[-96.501321,42.482749],[-96.525142,42.510234],[-96.611489,42.506088],[-96.62794545690168,42.52709613914179],[-96.658754,42.566426],[-96.7093,42.603753],[-96.697639,42.659143],[-96.778182,42.662993],[-96.801652,42.698774],[-96.80737060009817,42.70067898537299],[-96.906797,42.7338],[-96.965679,42.724532],[-97.01563111274717,42.75652546248819],[-97.02485,42.76243],[-97.131331,42.771929],[-97.16507039237378,42.791616641467684],[-97.213957,42.820143],[-97.237868,42.853139],[-97.302075,42.86566],[-97.341181,42.855882],[-97.417066,42.865918],[-97.452177,42.846048],[-97.48491687634198,42.8500032148679],[-97.515948,42.853752],[-97.59926,42.856229],[-97.63544209044147,42.85180907518548],[-97.70103,42.843797],[-97.801344,42.858003],[-97.857957,42.865093],[-97.876887,42.852663],[-97.905001,42.798872],[-97.950147,42.769619],[-98.035034,42.764205],[-98.1047,42.808475],[-98.14806,42.840013],[-98.15258665483817,42.84115338106369],[-98.231922,42.86114],[-98.280007,42.874996],[-98.30818681645127,42.88648920742559],[-98.386445,42.918407],[-98.434503,42.929227],[-98.478919,42.963539],[-98.49855,42.99856],[-98.847992,42.998255],[-99.25445501231657,42.998220926786686],[-99.53405501480898,42.998197488318084],[-99.850037,42.998171],[-100.198412611566,42.99797688463149],[-100.19841379977498,42.99797688396939],[-101.000429,42.99753],[-101.22810939311597,42.99786888252819],[-102.08248631919197,42.999140548519286],[-102.08254804307198,42.99914064038999],[-102.40864,42.999626],[-102.79211093983899,43.000036235770395],[-103.00089651607597,43.00025959379529],[-103.476133,43.000768],[-103.505099261632,43.00075881303118],[-104.053127,43.000585],[-104.053876,43.289801],[-104.05468456842698,43.47781554171099],[-104.05479428434798,43.503327530406],[-104.055032,43.558603],[-104.05548799845099,43.85347599845599],[-104.055488,43.853477],[-104.05541619070499,44.14108120678338],[-104.05540637782698,44.180382874095685],[-104.055389,44.249983],[-104.05569519926098,44.57099037714218],[-104.05581,44.691343],[-104.057698,44.997431]]]}}, {"type":"Feature","properties":{"name":"Utah","income":{"1995":35160,"1996":36360,"1997":38884,"1998":41380,"1999":43778,"2000":45934,"2001":45914,"2002":46165,"2003":46709,"2004":47224,"2005":48155,"2006":51373,"2007":55220,"2008":56820,"2009":55183,"2010":54740,"2011":55802,"2012":57067,"2013":59715,"2014":60943,"2015":62961}},"geometry":{"type":"Polygon","coordinates":[[[-114.052472,37.604776],[-114.05247199661397,37.60477664271939],[-114.051728,37.745997],[-114.049658,37.881368],[-114.049903,38.148601],[-114.04990337565798,38.148763026670586],[-114.050138,38.24996],[-114.05012,38.404536],[-114.050154,38.57292],[-114.05015362080597,38.57297521300339],[-114.04943670593099,38.677362456879585],[-114.048054,38.878693],[-114.049104,39.005509],[-114.047079,39.499943],[-114.04718141292597,39.54274360222969],[-114.047783,39.79416],[-114.04726815307697,39.906098113756194],[-114.046386,40.097896],[-114.04637281737297,40.116935833012185],[-114.046178,40.398313],[-114.045577,40.495801],[-114.043505,40.726292],[-114.04214514623497,40.999896577263286],[-114.042145,40.999926],[-114.041447,41.207752],[-114.040231,41.49169],[-114.039901,41.753781],[-114.041723,41.99372],[-113.817964,41.98858],[-113.496548,41.993305],[-113.249159,41.996203],[-113.000821,41.998223],[-113.00004013962398,41.99822761253908],[-112.648019,42.000307],[-112.264936,42.000991],[-112.15917745150998,41.99868192973779],[-112.109532,41.997598],[-112.10951205421198,41.99759809629469],[-111.750778,41.99933],[-111.50781303517599,41.99968566835219],[-111.50780619568698,41.999685678364294],[-111.471381,41.999739],[-111.374129,42.000893],[-111.046689,42.001567],[-111.04581846484197,41.57984494822579],[-111.045789,41.565571],[-111.0466,41.360692],[-111.04663698312598,41.25162695625139],[-111.046723,40.997959],[-110.539819,40.996346],[-110.121639,40.997101],[-110.04848299568498,40.99729729285058],[-110.00071673644098,40.99742545970819],[-109.715409,40.998191],[-109.250735,41.001009],[-109.050076,41.000659],[-109.048455,40.826081],[-109.04825975004798,40.66260181722799],[-109.048249,40.653601],[-109.05073211207697,40.22265525825759],[-109.050973,40.180849],[-109.050615,39.87497],[-109.05087192526199,39.660471777159394],[-109.05106684627299,39.49773880936619],[-109.051223831017,39.36667754958628],[-109.051512,39.126095],[-109.05996197258898,38.49998903102078],[-109.059962,38.499987],[-109.060062,38.275489],[-109.041762,38.16469],[-109.04179661485499,38.15303230496849],[-109.04260410062098,37.881084817492585],[-109.04378072050297,37.48481923141749],[-109.045223,36.999084],[-109.495338,36.999105],[-110.000677,36.997968],[-110.00068181858897,36.99796800029759],[-110.47019,36.997997],[-110.75068647892799,37.00319693472519],[-110.75069,37.003197],[-111.066496,37.002389],[-111.278286,37.000465],[-111.405869,37.001481],[-111.41278398787297,37.001477687156],[-112.35769,37.001025],[-112.538571,37.000744128882],[-112.545094,37.000734],[-112.82950194437198,37.000386401314394],[-112.89919089761598,37.000301228628395],[-112.966471,37.000219],[-113.965907,37.000025],[-114.0506,37.000396],[-114.051749,37.088434],[-114.051974,37.284511],[-114.052701,37.492014],[-114.052472,37.604776]]]}}, {"type":"Feature","properties":{"name":"Indiana","income":{"1995":34368,"1996":35502,"1997":37909,"1998":39719,"1999":40654,"2000":41511,"2001":42073,"2002":41973,"2003":43323,"2004":43217,"2005":44051,"2006":45414,"2007":47422,"2008":48010,"2009":45427,"2010":44616,"2011":46410,"2012":46954,"2013":47508,"2014":49384,"2015":50510}},"geometry":{"type":"Polygon","coordinates":[[[-88.05946949270077,37.8666898040108],[-88.040861,37.891767],[-88.016311,37.961574],[-88.030884,38.030713],[-87.98877,38.055591],[-87.96221,38.100054],[-87.927468,38.151946],[-87.975819,38.197834],[-87.97020084080388,38.23027105838579],[-87.968968,38.237389],[-87.908542,38.268581],[-87.831972,38.307241],[-87.779996,38.370842],[-87.75110594512049,38.41884920845479],[-87.74104,38.435576],[-87.714047,38.47988],[-87.654166,38.511911],[-87.660732,38.541092],[-87.64835676307446,38.56662871605759],[-87.637752,38.588512],[-87.62012,38.639489],[-87.545538,38.677613],[-87.498948,38.757774],[-87.521681,38.826576],[-87.53525705080847,38.85249146496739],[-87.54737,38.875614],[-87.52871766369788,38.90594378628919],[-87.527645,38.907688],[-87.529496,38.971925],[-87.579117,39.001607],[-87.572588,39.057286],[-87.625379,39.101806],[-87.63829341374408,39.15749254720249],[-87.640435,39.166727],[-87.577029,39.211123],[-87.593486,39.247452],[-87.59474584540598,39.25938361648299],[-87.600397,39.312904],[-87.578331,39.340343],[-87.531646,39.347888],[-87.531624,39.469378],[-87.53166668197439,39.47711099274289],[-87.53238528279098,39.60730494422149],[-87.532703,39.664868],[-87.53245449388427,39.88299911878229],[-87.532308,40.011587],[-87.53102161242799,40.14803539674569],[-87.530054,40.250671],[-87.52706526339918,40.47688229246149],[-87.52687577325378,40.49122440969039],[-87.526292,40.535409],[-87.52613649042368,40.736885081422884],[-87.526014,40.895582],[-87.52646330599117,41.01035481796449],[-87.52652,41.024837],[-87.52664815808238,41.16608994451159],[-87.52676788622747,41.29805160247919],[-87.526768,41.298177],[-87.52540935334748,41.47028066606168],[-87.52494,41.529735],[-87.524044,41.708335],[-87.470742,41.672835],[-87.415816,41.688183],[-87.365439,41.629536],[-87.261536,41.620336],[-87.22279994911838,41.62888983895999],[-87.125835,41.650302],[-87.027888,41.674661],[-86.93284902849437,41.716496937902185],[-86.90913,41.726938],[-86.824828,41.76024],[-86.64132292052079,41.75967493814279],[-86.640044,41.759671],[-86.52421974244288,41.759572155973494],[-86.501773,41.759553],[-86.22609434498737,41.76001595911639],[-86.22607,41.760016],[-86.06256302901056,41.75965303315798],[-85.791363,41.759051],[-85.79133496196276,41.75905103955749],[-85.65975023799089,41.75923668604699],[-85.29217881133349,41.75975527470178],[-85.232835,41.759839],[-85.19677420030199,41.759870841802986],[-84.82512828387678,41.76019900635189],[-84.805883,41.760216],[-84.806082,41.696089],[-84.80495815623958,41.53013781338819],[-84.80425325761149,41.426049711549894],[-84.804133,41.408292],[-84.80370357261688,41.27125833057059],[-84.80364498225556,41.25256168354819],[-84.803234,41.121414],[-84.80285962195138,40.98937405200859],[-84.80267020615337,40.92256871392099],[-84.802119,40.728163],[-84.80211903226376,40.72814593687259],[-84.80241387857939,40.57221288064669],[-84.802547,40.50181],[-84.80293136657127,40.46538662171978],[-84.804119,40.352844],[-84.80412052701489,40.35276223029709],[-84.80491730257837,40.31009591503409],[-84.808706,40.107216],[-84.81016123847448,40.00506754384819],[-84.81141710638047,39.916913629579795],[-84.81412813793278,39.72661651161929],[-84.814129,39.726556],[-84.81570594325547,39.56772166402739],[-84.81616019491078,39.521968108992894],[-84.817453,39.391753],[-84.81887709781039,39.30516616905229],[-84.81887746927508,39.305143583559385],[-84.820159,39.227225],[-84.820157,39.10548],[-84.860689,39.07814],[-84.897171,39.052407],[-84.87757023112478,39.031262844093995],[-84.849445,39.000923],[-84.832617,38.96146],[-84.877762,38.920357],[-84.86442851899166,38.91384364104939],[-84.830472,38.897256],[-84.786406,38.88222],[-84.79869982295229,38.85922739020669],[-84.803247,38.850723],[-84.812877,38.786087],[-84.856904,38.790224],[-84.962535,38.778035],[-85.02105214167419,38.758527324713896],[-85.071928,38.741567],[-85.146861,38.695427],[-85.187278,38.687609],[-85.20176062254856,38.69744079184628],[-85.238665,38.722494],[-85.275454,38.741172],[-85.33264073375139,38.73481675434769],[-85.340953,38.733893],[-85.400481,38.73598],[-85.448862,38.713368],[-85.438742,38.659319],[-85.43617,38.598292],[-85.43141607075218,38.58628561310889],[-85.4156,38.546341],[-85.43297226942606,38.52412339698789],[-85.433136,38.523914],[-85.474354,38.504074],[-85.498866,38.468242],[-85.587758,38.450495],[-85.621625,38.417089],[-85.6344441449773,38.37839944757479],[-85.646201,38.342916],[-85.683561,38.295469],[-85.750962,38.26787],[-85.79451090677007,38.27795473579529],[-85.816164,38.282969],[-85.839664,38.23977],[-85.894764,38.188469],[-85.89591178773559,38.17992692087039],[-85.905164,38.11107],[-85.922395,38.028679],[-85.95172964591549,38.01494012709058],[-85.976028,38.00356],[-85.99735165975429,37.99122560229909],[-86.033386,37.970382],[-86.095766,38.00893],[-86.206439,38.021876],[-86.278656,38.098509],[-86.321274,38.147418],[-86.35640726797098,38.13527783676579],[-86.387216,38.124632],[-86.43357436408806,38.087144387579485],[-86.434046,38.086763],[-86.471903,38.046218],[-86.48805246712828,38.04366530889968],[-86.521825,38.038327],[-86.525174,37.968228],[-86.509368,37.902887],[-86.599848,37.906754],[-86.615215,37.852857],[-86.64670305785909,37.864908975897784],[-86.658374,37.869376],[-86.722247,37.892648],[-86.779993,37.956522],[-86.810913,37.99715],[-86.81365994128528,37.99603449514159],[-86.875874,37.97077],[-86.927747,37.934956],[-86.97774142511018,37.92569920837269],[-87.010315,37.919668],[-87.043049,37.875049],[-87.057836,37.827457],[-87.105614,37.767631],[-87.137502,37.807264],[-87.180063,37.841375],[-87.25525,37.867326],[-87.270387407739,37.87542282658999],[-87.30405745244198,37.89343254912228],[-87.331765,37.908253],[-87.418585,37.944763],[-87.44863585760947,37.93387786821488],[-87.486347,37.920218],[-87.551277,37.925418],[-87.608479,37.898794],[-87.625851,37.851919],[-87.681633,37.855917],[-87.71321078529026,37.883088390366495],[-87.723635,37.892058],[-87.808013,37.875191],[-87.87254,37.920999],[-87.921744,37.907885],[-87.92539337830539,37.89959148487409],[-87.938128,37.870651],[-87.903804,37.817762],[-87.935861,37.789703],[-87.970262,37.781856],[-88.02803,37.799224],[-88.067364,37.856051],[-88.05946949270077,37.8666898040108]]]}}, {"type":"Feature","properties":{"name":"Massachusetts","income":{"1995":39025,"1996":40686,"1997":43015,"1998":44934,"1999":47604,"2000":49266,"2001":52092,"2002":51085,"2003":52713,"2004":53657,"2005":57176,"2006":59930,"2007":62383,"2008":65304,"2009":64057,"2010":62133,"2011":63126,"2012":65378,"2013":66794,"2014":69200,"2015":70659}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-70.275526,41.310464],[-70.193712,41.313787],[-70.079133,41.319504],[-70.049053,41.391702],[-69.984869,41.358818],[-69.960181,41.264546],[-70.015225,41.237964],[-70.096967,41.24085],[-70.211479,41.248765],[-70.275526,41.310464]]],[[[-70.833802,41.353386],[-70.757797,41.365702],[-70.686881,41.441334],[-70.603555,41.482384],[-70.553277,41.452955],[-70.496197,41.424908],[-70.463833,41.419145],[-70.448262,41.353651],[-70.577454,41.349163],[-70.693635,41.342833],[-70.768687,41.303702],[-70.821284,41.251014],[-70.833397,41.316778],[-70.833802,41.353386]]],[[[-73.508142,42.086257],[-73.41064440742727,42.35174629964789],[-73.38350565728358,42.42564605018379],[-73.352527,42.510002],[-73.35252495494419,42.51000750995059],[-73.30700407618058,42.63265345141149],[-73.264957,42.74594],[-73.14249512051438,42.743425717196885],[-73.02301789329009,42.74097271272689],[-73.01864861335038,42.740883006399784],[-72.93026261251798,42.73906834045759],[-72.86429185484538,42.737713885159195],[-72.809113,42.736581],[-72.51671118278219,42.728467669829186],[-72.458519,42.726853],[-72.45119505182268,42.726650885493584],[-72.41203006475229,42.72557007336329],[-72.28303409251089,42.722010250623995],[-72.20361347980676,42.71981852867989],[-72.124526,42.717636],[-72.08136505018797,42.716456538541195],[-71.92903005905349,42.71229367253259],[-71.89876877193657,42.71146672080879],[-71.80538960273827,42.70891494352849],[-71.745817,42.707287],[-71.636214,42.704888],[-71.351874,42.698154],[-71.294205,42.69699],[-71.255605,42.736389],[-71.25511012181057,42.73639705328719],[-71.24538403292068,42.73655532857459],[-71.181803,42.73759],[-71.186104,42.790689],[-71.149703,42.815489],[-71.11637501217747,42.81190291443509],[-71.064201,42.806289],[-71.04871641369859,42.83106433808219],[-71.031201,42.859089],[-70.9665,42.868989],[-70.930799,42.884589],[-70.86475,42.870258],[-70.817296,42.87229],[-70.80522,42.781798],[-70.772267,42.711064],[-70.72982,42.669602],[-70.681594,42.662342],[-70.645101,42.689423],[-70.602506,42.677702],[-70.594014,42.63503],[-70.654727,42.582234],[-70.698574,42.577393],[-70.804091,42.561595],[-70.848492,42.550195],[-70.835991,42.490496],[-70.886493,42.470197],[-70.89923397910178,42.44991565568648],[-70.905993,42.43915651159219],[-70.913192,42.427697],[-70.95521106146327,42.42546909039169],[-70.982994,42.423996],[-70.98254560158787,42.42022180005199],[-70.974897,42.355843],[-70.9758929421261,42.35433925372189],[-70.98309358594719,42.34346719493309],[-70.997838,42.321205],[-70.99305963994819,42.31289228041239],[-70.967351,42.268168],[-70.94849704353429,42.28235469378229],[-70.91749,42.305686],[-70.881242,42.300663],[-70.851093,42.26827],[-70.83585177539437,42.26476326471339],[-70.788724,42.25392],[-70.78157454556846,42.248636946023886],[-70.73056,42.21094],[-70.685315,42.133025],[-70.67923777450248,42.12634945942249],[-70.63848,42.081579],[-70.644337,42.045895],[-70.678798,42.00551],[-70.662476,41.960592],[-70.608166,41.940701],[-70.583572,41.950007],[-70.546386,41.916751],[-70.525567,41.85873],[-70.54103,41.815754],[-70.53640725412478,41.81163414574639],[-70.494048,41.773883],[-70.441718,41.752898],[-70.323819,41.736058],[-70.272289,41.721346],[-70.216073,41.742981],[-70.121978,41.758841],[-70.024734,41.787364],[-70.003842,41.80852],[-70.006111,41.852396],[-70.06901,41.884924],[-70.074006,41.93865],[-70.07657399913668,41.957942458249995],[-70.083775,42.012041],[-70.15076,42.026569],[-70.190834,42.020028],[-70.245385,42.063733],[-70.189305,42.082337],[-70.138942,42.092907],[-70.049382,42.064689],[-69.994136,41.999258],[-69.98023136158768,41.94598646023329],[-69.974781,41.925105],[-69.935952,41.809422],[-69.928261,41.6917],[-69.931129,41.622659],[-69.964982,41.55111],[-70.011229,41.543931],[-70.011961,41.619797],[-70.007011,41.671579],[-70.055523,41.664843],[-70.158621,41.650438],[-70.269687,41.617775],[-70.321588,41.630508],[-70.400581,41.606382],[-70.445289,41.591815],[-70.476256,41.558502],[-70.559689,41.54833],[-70.654104,41.519025],[-70.66905836660058,41.512929662674594],[-70.734306,41.486335],[-70.79027,41.446339],[-70.857528,41.425767],[-70.948431,41.409193],[-70.934986,41.454699],[-70.806861,41.497583],[-70.72608894480699,41.54323693191759],[-70.698197,41.559002],[-70.695392,41.602546],[-70.71597984466878,41.61401326876418],[-70.76177007978838,41.639518072270384],[-70.765463,41.641575],[-70.80396261320789,41.60151554100029],[-70.82191,41.582841],[-70.853121,41.587321],[-70.85762366603339,41.586512092463494],[-70.90909177644679,41.57726580546549],[-70.910165,41.577073],[-70.941785,41.540121],[-70.981708,41.51007],[-71.02032123222438,41.50215947591698],[-71.035514,41.499047],[-71.085663,41.509292],[-71.12057,41.497448],[-71.137492,41.602561],[-71.132888,41.660102],[-71.19564,41.67509],[-71.20132718752488,41.681768328202686],[-71.20860053289508,41.69030924360269],[-71.261392,41.752301],[-71.31726409756008,41.77719466337239],[-71.329396,41.7826],[-71.339597,41.832],[-71.339298,41.893399],[-71.3817,41.893199],[-71.381461,41.952141],[-71.38143134689308,41.985084119129496],[-71.381401,42.018798],[-71.45808099455608,42.01687882512869],[-71.49822401312468,42.01587411101849],[-71.559439,42.014342],[-71.591096527631,42.013513343557186],[-71.60620344113408,42.0131179102388],[-71.799242,42.008065],[-71.80065,42.023569],[-71.88467683590369,42.025059351484295],[-71.987326,42.02688],[-72.10215943452678,42.028630240054795],[-72.13573146194668,42.02914192994159],[-72.19884597813198,42.030103893281996],[-72.317148,42.031907],[-72.39747625519588,42.03281619113578],[-72.50917933629829,42.03408049659008],[-72.528131,42.034295],[-72.607933,42.030795],[-72.735496,42.036399],[-72.766739,42.002995],[-72.77475931607859,42.00212910418029],[-72.810078,41.998316],[-72.847142,42.036894],[-72.999549,42.038653],[-73.00876278163068,42.03890341624669],[-73.05336267374808,42.040115571910285],[-73.12722917087838,42.04212314835478],[-73.231056,42.044945],[-73.487314,42.049638],[-73.48967994203208,42.05379770958669],[-73.508142,42.086257]]]]}}, {"type":"Feature","properties":{"name":"Mississippi","income":{"1995":26501,"1996":26901,"1997":28527,"1998":28925,"1999":30739,"2000":32542,"2001":30877,"2002":31434,"2003":32397,"2004":34278,"2005":33090,"2006":34615,"2007":36424,"2008":37818,"2009":36764,"2010":36992,"2011":36963,"2012":37179,"2013":38191,"2014":39738,"2015":40630}},"geometry":{"type":"Polygon","coordinates":[[[-91.621358,31.267811],[-91.564192,31.261633],[-91.508858,31.291644],[-91.536061,31.338355],[-91.532336,31.390275],[-91.510356,31.438928],[-91.51714,31.498394],[-91.489618,31.534266],[-91.437616,31.546166],[-91.457517,31.587566],[-91.463817,31.620365],[-91.395715,31.644165],[-91.380915,31.732464],[-91.38012452998348,31.732626953049998],[-91.318576,31.745315],[-91.32045873328158,31.74780061448219],[-91.359514,31.799362],[-91.345714,31.842861],[-91.290135,31.833658],[-91.24401516132468,31.86973243750389],[-91.234899,31.876863],[-91.18111,31.920059],[-91.17741,31.973257],[-91.117409,31.987057],[-91.080808,32.023456],[-91.079108,32.050255],[-91.034707,32.101053],[-91.03947231890697,32.10796814266529],[-91.108509,32.20815],[-90.991227,32.214662],[-90.947834,32.283486],[-90.92117,32.342073],[-90.986672,32.35176],[-90.965986,32.424806],[-91.052907,32.438442],[-91.060516,32.512361],[-91.011275,32.516596],[-91.04876042776367,32.57279704042139],[-91.049312,32.573624],[-91.05529310494987,32.5789835010771],[-91.079506,32.60068],[-91.098762,32.685291],[-91.056999,32.72558],[-91.113652,32.73997],[-91.157614,32.776033],[-91.161669,32.812465],[-91.13789,32.848975],[-91.070602,32.888659],[-91.072075,32.937832],[-91.134414,32.980533],[-91.166073,33.004106],[-91.15960609801297,33.01124232130679],[-91.120379,33.05453],[-91.180836,33.098364],[-91.153015,33.135093],[-91.104317,33.131598],[-91.084366,33.180856],[-91.068708,33.232936],[-91.086137,33.273652],[-91.125539,33.280255],[-91.142219,33.348989],[-91.113764,33.393124],[-91.147663,33.427172],[-91.171799,33.462342],[-91.189375,33.493005],[-91.215671,33.529423],[-91.20564498594787,33.54697837093289],[-91.188942,33.576225],[-91.130902,33.610919],[-91.178311,33.651109],[-91.10098,33.660551],[-91.075389,33.714403],[-91.143287,33.747141],[-91.111494,33.774568],[-91.08551,33.77641],[-91.026782,33.763642],[-91.025173,33.805953],[-91.052819,33.824181],[-91.061247,33.877505],[-91.026382,33.90798],[-91.035961,33.943758],[-91.088696,33.961334],[-91.048367,33.985078],[-91.004981,33.977011],[-90.979945,34.000106],[-90.942662,34.01805],[-90.89242,34.02686],[-90.874541,34.072041],[-90.90113,34.094667],[-90.946323,34.109374],[-90.94479552430947,34.11665720531419],[-90.94408076019378,34.12006529477739],[-90.938064,34.148754],[-90.894385,34.160953],[-90.882701,34.184364],[-90.89456,34.22438],[-90.839981,34.236114],[-90.812829,34.279438],[-90.752681,34.289266],[-90.765174,34.342818],[-90.729131,34.364206],[-90.660404,34.33576],[-90.641398,34.383869],[-90.575336,34.415152],[-90.583717,34.458829],[-90.569347,34.524867],[-90.549244,34.568101],[-90.587224,34.615732],[-90.57328841261827,34.63367050646799],[-90.550158,34.663445],[-90.546053,34.702076],[-90.505494,34.764568],[-90.473527,34.788835],[-90.463795,34.834923],[-90.40798275379427,34.83526597928069],[-90.401633,34.835305],[-90.313476,34.871698],[-90.31142425034518,34.87285114409999],[-90.250095,34.90732],[-90.244476,34.937596],[-90.309297,34.995694],[-89.795187,34.994293],[-89.75961264223437,34.99423977173149],[-89.72431583796856,34.994186958753495],[-89.64428383409208,34.994067210562484],[-89.434954,34.993754],[-89.35267939184838,34.99399614174589],[-89.19828790149498,34.994450530115095],[-89.02654,34.994956],[-89.01712701155239,34.99496761283629],[-88.823050501632,34.995207045695],[-88.786612,34.995252],[-88.469877,34.996033],[-88.38049251152206,34.995792408222094],[-88.36353026853918,34.99574675179709],[-88.258111,34.995463],[-88.200064,34.995634],[-88.154617,34.922392],[-88.097888,34.892202],[-88.134263,34.62266],[-88.13955944124736,34.581696745883896],[-88.15490218400868,34.46303430043999],[-88.17326173459489,34.32103953433429],[-88.20358349521936,34.08652773146809],[-88.207229,34.058333],[-88.24838747390947,33.74490759488169],[-88.254445,33.698779],[-88.27451647078367,33.53400147778519],[-88.30444281351036,33.28832],[-88.317135,33.184123],[-88.34008499213928,32.991264337874995],[-88.34749024783488,32.92903478688049],[-88.373338,32.711825],[-88.38924856412427,32.578122395958594],[-88.42131222139429,32.30867912301129],[-88.428278,32.250143],[-88.43114536346278,32.22763623468889],[-88.45338776310928,32.0530492054197],[-88.46866,31.933173],[-88.46866248405128,31.893855711615586],[-88.468669,31.790722],[-88.46362530468488,31.697942371350187],[-88.459478,31.621652],[-88.44944606901707,31.435836861277593],[-88.44866,31.421277],[-88.432007,31.114298],[-88.42602096378707,30.99828135743029],[-88.41246743135916,30.735597459215292],[-88.41227,30.731771],[-88.403931,30.543359],[-88.395023,30.369425],[-88.409927,30.342115],[-88.446495,30.347753],[-88.471875,30.32002],[-88.522494,30.340092],[-88.581929,30.331063],[-88.613006,30.353964],[-88.66382,30.362099],[-88.700587,30.343689],[-88.746945,30.347622],[-88.80034351520347,30.35726417309489],[-88.818762,30.36059],[-88.89393,30.393398],[-88.971233,30.390798],[-89.083237,30.368097],[-89.18684,30.331197],[-89.294444,30.307596],[-89.30702376084449,30.303994780244096],[-89.344746,30.293196],[-89.424624,30.245391],[-89.447465,30.205098],[-89.475824,30.191561],[-89.524504,30.180753],[-89.607655,30.217096],[-89.634208,30.308256],[-89.678514,30.414012],[-89.69993208284077,30.454036880785996],[-89.712493,30.47751],[-89.791664,30.551524],[-89.821868,30.644024],[-89.82618035911518,30.668823270185197],[-89.836331,30.727197],[-89.791745,30.820387],[-89.750073,30.91293],[-89.72817569016057,31.00231388798409],[-89.728147,31.002431],[-89.83590782432817,31.002101423117598],[-89.897516,31.001913],[-90.25955494049128,31.00066178122909],[-90.346007,31.000363],[-90.34724108066209,31.00036066798079],[-90.54757442523307,30.999982101791588],[-90.56719540065848,30.99994502439989],[-90.758775,30.999583],[-90.82582914129189,30.99952535534059],[-91.06012746799657,30.99932393530919],[-91.17614012396687,30.99922420231859],[-91.224068,30.999183],[-91.636942,30.999416],[-91.62825729820878,31.00509700189519],[-91.560365,31.049508],[-91.594693,31.091444],[-91.621671,31.13687],[-91.59099389306448,31.191998565698793],[-91.590051,31.193693],[-91.644356,31.234414],[-91.621358,31.267811]]]}}, {"type":"Feature","properties":{"name":"Nebraska","income":{"1995":32176,"1996":33562,"1997":35337,"1998":37233,"1999":38668,"2000":40429,"2001":41091,"2002":41130,"2003":41984,"2004":42166,"2005":43675,"2006":45369,"2007":47072,"2008":49731,"2009":47470,"2010":48415,"2011":50281,"2012":50766,"2013":51502,"2014":52803,"2015":55073}},"geometry":{"type":"Polygon","coordinates":[[[-104.053142,41.114457],[-104.052453,41.278202],[-104.05228713412097,41.393214000193396],[-104.052287,41.393307],[-104.05263457163298,41.564275779573684],[-104.052735,41.613676],[-104.05282523523898,41.69795385306399],[-104.053026,41.885464],[-104.05276213709197,42.00171826586659],[-104.052729,42.016318],[-104.052793,42.249962],[-104.053107,42.499964],[-104.05266219156799,42.61176630054148],[-104.052586,42.630917],[-104.053127,43.000585],[-103.505099261632,43.00075881303118],[-103.476133,43.000768],[-103.00089651607597,43.00025959379529],[-102.79211093983899,43.000036235770395],[-102.40864,42.999626],[-102.08254804307198,42.99914064038999],[-102.08248631919197,42.999140548519286],[-101.22810939311597,42.99786888252819],[-101.000429,42.99753],[-100.19841379977498,42.99797688396939],[-100.198412611566,42.99797688463149],[-99.850037,42.998171],[-99.53405501480898,42.998197488318084],[-99.25445501231657,42.998220926786686],[-98.847992,42.998255],[-98.49855,42.99856],[-98.478919,42.963539],[-98.434503,42.929227],[-98.386445,42.918407],[-98.30818681645127,42.88648920742559],[-98.280007,42.874996],[-98.231922,42.86114],[-98.15258665483817,42.84115338106369],[-98.14806,42.840013],[-98.1047,42.808475],[-98.035034,42.764205],[-97.950147,42.769619],[-97.905001,42.798872],[-97.876887,42.852663],[-97.857957,42.865093],[-97.801344,42.858003],[-97.70103,42.843797],[-97.63544209044147,42.85180907518548],[-97.59926,42.856229],[-97.515948,42.853752],[-97.48491687634198,42.8500032148679],[-97.452177,42.846048],[-97.417066,42.865918],[-97.341181,42.855882],[-97.302075,42.86566],[-97.237868,42.853139],[-97.213957,42.820143],[-97.16507039237378,42.791616641467684],[-97.131331,42.771929],[-97.02485,42.76243],[-97.01563111274717,42.75652546248819],[-96.965679,42.724532],[-96.906797,42.7338],[-96.80737060009817,42.70067898537299],[-96.801652,42.698774],[-96.778182,42.662993],[-96.697639,42.659143],[-96.7093,42.603753],[-96.658754,42.566426],[-96.62794545690168,42.52709613914179],[-96.611489,42.506088],[-96.525142,42.510234],[-96.501321,42.482749],[-96.445508,42.49063],[-96.381307,42.461694],[-96.411808,42.410894],[-96.407998,42.337408],[-96.35195719249597,42.280894704543286],[-96.336003,42.264806],[-96.336323,42.218922],[-96.33721609470588,42.2148495068956],[-96.347752,42.166806],[-96.2689,42.11359],[-96.272877,42.047238],[-96.223611,42.022652],[-96.132537,41.974625],[-96.159098,41.910057],[-96.12682125346538,41.86609524770159],[-96.107911,41.840339],[-96.064537,41.793002],[-96.0876,41.72218],[-96.10793787174647,41.676508989762084],[-96.111483,41.668548],[-96.118105,41.613495],[-96.09182,41.561086],[-96.080493,41.528199],[-96.005079,41.544004],[-95.99402039301187,41.506890640941485],[-95.982962,41.469778],[-95.922529,41.455766],[-95.92733624232008,41.38998793745959],[-95.92879,41.370096],[-95.92569,41.322197],[-95.890152,41.278308],[-95.911391,41.237998],[-95.90990849125477,41.191282850827896],[-95.90969,41.184398],[-95.856788,41.187098],[-95.86189806820938,41.160302348212696],[-95.868688,41.124698],[-95.863839,41.083507],[-95.86478476408527,41.05284550461349],[-95.865878,41.017403],[-95.828329,40.972378],[-95.837774,40.924712],[-95.81872727856988,40.89794806640649],[-95.810709,40.886681],[-95.841309,40.845604],[-95.83424381671439,40.78378438704309],[-95.834156,40.783016],[-95.888697,40.736292],[-95.846034,40.682605],[-95.781909,40.653272],[-95.748626,40.603355],[-95.765645,40.585208],[-95.75711,40.52599],[-95.714291,40.527208],[-95.71228037180106,40.52375442620738],[-95.694726,40.493602],[-95.684363,40.463366],[-95.649418,40.396149],[-95.641027,40.366399],[-95.653729,40.322582],[-95.598657,40.309809],[-95.553292,40.291158],[-95.54818200118008,40.26441467284269],[-95.54787031627028,40.26278346081979],[-95.54716,40.259066],[-95.472548,40.236078],[-95.48102,40.188524],[-95.432165,40.141025],[-95.394216,40.108263],[-95.414734,40.06982],[-95.382957,40.027112],[-95.348777,40.029297],[-95.30829,39.999998],[-95.33989597085028,40.00002885710539],[-95.784575,40.000463],[-95.78811099489167,40.00046677936529],[-96.01067881793449,40.00070466577199],[-96.02409,40.000719],[-96.154365,40.000495],[-96.239172,40.000691],[-96.23920787841108,40.00069104275439],[-96.46371207677477,40.00095857255448],[-96.469945,40.000966],[-96.805768,40.001368455095395],[-96.873812,40.00145],[-96.91640700546577,40.00145409104389],[-97.009165,40.001463],[-97.36919903531498,40.00193930576049],[-97.415833,40.002001],[-97.777155,40.002167],[-97.82150081227518,40.002186882088886],[-97.93182492631716,40.00223634501959],[-98.076034,40.002301],[-98.27401705975288,40.00233745072989],[-98.50445498363678,40.002379876736],[-98.613755,40.0024],[-98.72637296393899,40.00233627316689],[-99.06701834989808,40.00214351305219],[-99.085597,40.002133],[-99.17913315086108,40.00210895269489],[-99.501792,40.002026],[-99.62532672639958,40.00177782764698],[-99.62825384922449,40.00177194726839],[-99.813401,40.0014],[-100.17779754587897,40.00156581385159],[-100.19359,40.001573],[-100.19359905683599,40.00157300571989],[-100.477018,40.001752],[-100.73882471319098,40.002262956567684],[-100.75883,40.002302],[-101.060317,40.002307],[-101.293991,40.002559],[-101.32551402751898,40.00256534823049],[-101.41102898780197,40.002582569567586],[-101.542273,40.002609],[-101.832161,40.002933],[-102.051744,40.003078],[-102.051309,40.338381],[-102.05130855184399,40.34922135687219],[-102.05130479859699,40.44000799337699],[-102.05129415157899,40.697546832388994],[-102.05129200020698,40.74958599487369],[-102.051292,40.749591],[-102.051614,41.002377],[-102.05171751637799,41.00237696762389],[-102.556789,41.002219],[-102.62103302445198,41.002223202615596],[-102.65346413726898,41.00222532414359],[-103.076536,41.002253],[-103.38249165188998,41.001926146620995],[-103.573774006195,41.00172179908409],[-103.574522,41.001721],[-104.053249,41.001406],[-104.053142,41.114457]]]}}, {"type":"Feature","properties":{"name":"New Mexico","income":{"1995":27929,"1996":27014,"1997":30836,"1998":31445,"1999":32671,"2000":34487,"2001":33733,"2002":34827,"2003":35091,"2004":37838,"2005":37603,"2006":40610,"2007":41509,"2008":43719,"2009":42830,"2010":42186,"2011":42097,"2012":42828,"2013":44026,"2014":44905,"2015":45524}},"geometry":{"type":"Polygon","coordinates":[[[-109.049195,31.796551],[-109.048296,32.084093],[-109.04761200321998,32.426375388514195],[-109.047612,32.426377],[-109.047117,32.77757],[-109.04711706230997,32.777794000947694],[-109.04723698053698,33.20889503155078],[-109.047237,33.208965],[-109.047298,33.409783],[-109.04660747392198,33.77822380035048],[-109.046426,33.875052],[-109.046182,34.522393],[-109.04613893536299,34.57929101281789],[-109.045851,34.959718],[-109.04585123518297,34.959818515836695],[-109.04635589438398,35.17550718835119],[-109.046796,35.363606],[-109.046296,35.614251],[-109.046024,35.8798],[-109.04587116820498,36.002701630519],[-109.045729,36.117028],[-109.045433,36.874589],[-109.045223,36.999084],[-108.620309,36.999287],[-108.37930295009397,36.999564686311494],[-108.000623,37.000001],[-107.48173699915498,37.00000458031429],[-107.42092190574498,37.00000499993859],[-107.420913,37.000005],[-106.877292,37.000139],[-106.869796,36.992426],[-106.476233588828,36.99377410054689],[-106.343139,36.99423],[-106.00631641079798,36.995386628817286],[-105.997472,36.995417],[-105.71846968399099,36.995845927301],[-105.716471,36.995849],[-105.533922,36.995875],[-105.41931,36.995856],[-105.251296,36.995605],[-105.22050520078098,36.99556323648649],[-105.15504274804798,36.9954744456106],[-105.1208,36.995428],[-104.732031,36.993447],[-104.338833,36.993535],[-104.00784940961297,36.995984094709094],[-103.733247,36.998016],[-103.08610107563098,36.99986436110639],[-103.002199,37.000104],[-103.001964,36.909573],[-103.002518,36.675186],[-103.002188,36.602716],[-103.002434,36.500397],[-103.041924,36.500439],[-103.040824,36.055231],[-103.04135672181798,35.73943350634869],[-103.04155399893398,35.62248763195869],[-103.041554,35.622487],[-103.04261795056497,35.1831572590084],[-103.042711,35.144735],[-103.04273881860799,34.95414204036139],[-103.042769,34.747361],[-103.043072,34.619782],[-103.043946,34.379555],[-103.04385030117197,34.31274987350789],[-103.043835830165,34.302648],[-103.04356392079099,34.11283438975539],[-103.043516,34.079382],[-103.047346,33.824675],[-103.04734601816698,33.824674123151695],[-103.05261,33.570599],[-103.05261051656397,33.57057477644219],[-103.056495064338,33.38841421462059],[-103.060103,33.219225],[-103.06346888847497,32.959106381830495],[-103.064889,32.849359],[-103.064761,32.587983],[-103.064696,32.522193],[-103.064422,32.145006],[-103.06442240110597,32.087051],[-103.064423,32.000518],[-103.326501,32.00037],[-103.72288197914799,32.00016556867639],[-103.98021347738099,32.00003285136259],[-104.024521,32.00001],[-104.643526,32.000443],[-104.84774,32.000464602834995],[-104.91835699427997,32.000472073073496],[-105.153994,32.000497],[-105.750527,32.002206],[-105.99797115166398,32.00197459069899],[-106.200699,32.001785],[-106.37717318824697,32.00124010103749],[-106.618486,32.000495],[-106.630114,31.971258],[-106.623445,31.914034],[-106.63588,31.871514],[-106.581344,31.813906],[-106.528242,31.783148],[-106.531731,31.78391],[-106.993544,31.783689],[-107.29679299041398,31.783625337107992],[-107.422246,31.783599],[-108.208394,31.783599],[-108.208572,31.499742],[-108.208573,31.333395],[-108.707657,31.333191],[-108.861028,31.332315],[-109.050044,31.332502],[-109.049195,31.796551]]]}}, {"type":"Feature","properties":{"name":"North Carolina","income":{"1995":31987,"1996":34487,"1997":35320,"1998":35982,"1999":37563,"2000":38889,"2001":39072,"2002":38194,"2003":39438,"2004":40863,"2005":40781,"2006":42721,"2007":44772,"2008":46574,"2009":43754,"2010":43417,"2011":44028,"2012":45195,"2013":45946,"2014":46596,"2015":47884}},"geometry":{"type":"Polygon","coordinates":[[[-84.28659837874088,35.20575821849589],[-84.28322,35.226577],[-84.223718,35.269078],[-84.178516,35.240679],[-84.097508,35.247382],[-84.02910441377247,35.29212377649389],[-84.02351,35.295783],[-84.038081,35.348363],[-84.007586,35.371661],[-84.021782,35.407418],[-83.973171,35.452582],[-83.95891783456389,35.45789943957989],[-83.95323138015038,35.46002088957669],[-83.916801,35.473612],[-83.848502,35.519259],[-83.771736,35.562118],[-83.66291190158928,35.567799793208295],[-83.653159,35.568309],[-83.587827,35.566963],[-83.498335,35.562981],[-83.452431,35.602918],[-83.421576,35.611186],[-83.347262,35.660474],[-83.297154,35.65775],[-83.26474416829,35.70308949617009],[-83.25614155230359,35.715124062657786],[-83.255351,35.71623],[-83.198267,35.725494],[-83.161537,35.763363],[-83.097193,35.776067],[-83.04853,35.787706],[-82.978414,35.78261],[-82.96664974289857,35.795445979573984],[-82.937437,35.82732],[-82.899718,35.874602],[-82.910608,35.92693],[-82.89375141843136,35.93385726970889],[-82.860724,35.94743],[-82.81613,35.923986],[-82.787465,35.952163],[-82.779397,35.992511],[-82.725065,36.018204],[-82.628365,36.062105],[-82.60570361079358,36.03719886356189],[-82.595525,36.026012],[-82.610885,35.974442],[-82.557874,35.953901],[-82.50800765972248,35.98201320544148],[-82.464558,36.006508],[-82.41693759467316,36.07297001070849],[-82.409458,36.083409],[-82.346857,36.115209],[-82.297655,36.13351],[-82.26569,36.127614],[-82.22025301028657,36.15382003984309],[-82.211251,36.159012],[-82.140847,36.136216],[-82.127146,36.104417],[-82.08114891713238,36.105692114332584],[-82.080143,36.10572],[-82.02874,36.124322],[-81.960101,36.228131],[-81.93436924449257,36.264716204379795],[-81.91844447290477,36.287357917382096],[-81.908137,36.302013],[-81.833202,36.347339],[-81.768977,36.341042],[-81.705966,36.338496],[-81.72537277968526,36.38973849743609],[-81.734312,36.413342],[-81.695311,36.467912],[-81.699962,36.536829],[-81.677535,36.588117],[-81.499831,36.57982],[-81.35322122460218,36.57623823115639],[-81.176712,36.571926],[-81.061866,36.56702],[-80.901726,36.561751],[-80.90166111892098,36.56175118716799],[-80.84021307724598,36.56192845163729],[-80.704831,36.562319],[-80.61218878812458,36.55821627638039],[-80.44006854346448,36.550593813802195],[-80.431605,36.550219],[-80.295243,36.543973],[-80.05345504335008,36.542639428086595],[-80.02733891514119,36.54249538561418],[-80.027269,36.542495],[-79.89167016695387,36.54203383661619],[-79.71485081105197,36.54143248474129],[-79.51364766250857,36.54074820507069],[-79.510647,36.540738],[-79.47005667392429,36.54083614978659],[-79.3428439209599,36.54114375767659],[-79.21845549592226,36.541444536176094],[-79.13833589887138,36.54163827005589],[-78.942009,36.542113],[-78.79627395514048,36.541759493581594],[-78.73412280111718,36.54160873484079],[-78.509965,36.541065],[-78.45727789625586,36.541448708399486],[-78.32371850955899,36.54242139155859],[-78.132911,36.543811],[-78.04620830436028,36.54419767268659],[-77.89977414050628,36.54485073302249],[-77.76710333422477,36.545442412170495],[-77.749706,36.54552],[-77.29877018881177,36.546039010854486],[-77.190175,36.546164],[-77.16432273355687,36.546152819904094],[-76.917318,36.546046],[-76.91603763285619,36.54608133029029],[-76.91573180234968,36.546089769338884],[-76.738329,36.550985],[-76.54196586571828,36.55078453236009],[-76.49148257547228,36.55073299383639],[-76.31330296826026,36.550551089806994],[-76.313215,36.550551],[-76.12234994701008,36.55055233255409],[-76.02675,36.550553],[-75.867044,36.550754],[-75.838437,36.434897],[-75.79641,36.290351],[-75.77065146255967,36.23208030705078],[-75.71831,36.113674],[-75.658537,36.02043],[-75.569794,35.863301],[-75.51901,35.769087],[-75.496086,35.728515],[-75.458659,35.596597],[-75.486771,35.391652],[-75.533627,35.225825],[-75.635493,35.22026],[-75.74956142396219,35.18561636219219],[-75.757916,35.183079],[-75.912985,35.1196],[-76.013145,35.061855],[-76.137269,34.987858],[-76.233088,34.905477],[-76.31021,34.852309],[-76.386804,34.784579],[-76.450454,34.71445],[-76.535946,34.588577],[-76.553806,34.628252],[-76.618719,34.67255],[-76.726969,34.69669],[-76.906257,34.68282],[-77.11296439307677,34.638092832391486],[-77.136843,34.632926],[-77.240991,34.587507],[-77.322524,34.535574],[-77.462922,34.471354],[-77.51521654458477,34.437384969426596],[-77.635034,34.359555],[-77.71351317045878,34.29024718668679],[-77.764022,34.245641],[-77.829209,34.162618],[-77.915536,33.971723],[-77.93482713508568,33.92054850579729],[-77.960172,33.853315],[-78.006765,33.858704],[-78.018689,33.888289],[-78.136952,33.912178],[-78.276147,33.912364],[-78.383964,33.901946],[-78.541087,33.851112],[-78.615932,33.915523],[-78.65088747609119,33.94506940996439],[-78.81171,34.081006],[-79.071169,34.29924],[-79.358317,34.545358],[-79.45027745772619,34.6206091350416],[-79.46196554440178,34.63017348270309],[-79.675299,34.804744],[-79.69294834227739,34.80496233115169],[-79.92468425313638,34.807829019751495],[-79.92810346909137,34.80787131715529],[-80.077223,34.809716],[-80.32083257112978,34.81362082154399],[-80.561657,34.817481],[-80.56167339135038,34.817481445270296],[-80.796997,34.823874],[-80.782042,34.935782],[-80.84056591565317,35.00147041441789],[-80.90348118671209,35.07208777404609],[-80.90623995408248,35.07518426976559],[-80.93495,35.107409],[-81.041489,35.044703],[-81.058029,35.07319],[-81.036759,35.122552],[-81.04226581176299,35.146608594145796],[-81.04287,35.149248],[-81.3280909892918,35.16228591555739],[-81.36760858859688,35.16409232932819],[-81.494265,35.169882],[-81.76806906135857,35.17970536192819],[-81.87411220431628,35.183509908026295],[-81.96935840125757,35.18692708840049],[-82.039651,35.189449],[-82.04839122964786,35.18963754337549],[-82.21624871922907,35.19325854865318],[-82.295354,35.194965],[-82.35302152309048,35.19870416046639],[-82.411301,35.202483],[-82.455609,35.177425],[-82.53256,35.155617],[-82.57771554495088,35.14647526757419],[-82.68604,35.124545],[-82.746431,35.079131],[-82.76205955211358,35.08187443600409],[-82.783283,35.0856],[-82.897499,35.056021],[-83.00843480376807,35.02692851150739],[-83.108606,35.000659],[-83.10861299650726,35.00065884367769],[-83.322768,34.995874],[-83.48287320429068,34.990873961286795],[-83.54918075350466,34.988803195913995],[-83.619985,34.986592],[-83.93642734425198,34.98748438337969],[-83.936646,34.987485],[-84.00533673343827,34.98764958401229],[-84.12944696263588,34.98794695395529],[-84.321869,34.988408],[-84.28659837874088,35.20575821849589]]]}}, {"type":"Feature","properties":{"name":"Rhode Island","income":{"1995":34611,"1996":36402,"1997":36699,"1998":39907,"1999":40965,"2000":42305,"2001":43884,"2002":43115,"2003":45006,"2004":47037,"2005":50415,"2006":51324,"2007":52755,"2008":54562,"2009":53243,"2010":52053,"2011":53152,"2012":54002,"2013":55015,"2014":54797,"2015":57265}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-71.631472,41.166678],[-71.593342,41.237428],[-71.54541,41.24273],[-71.534084,41.181862],[-71.51921,41.149624],[-71.5937,41.146339],[-71.631472,41.166678]]],[[[-71.860513,41.320248],[-71.835951,41.353935],[-71.839649,41.412119],[-71.797683,41.416709],[-71.79171906174719,41.54577200433499],[-71.78935867274228,41.59685216034269],[-71.789356,41.59691],[-71.78946459083899,41.64001719070689],[-71.78967758183198,41.724568000295285],[-71.789678,41.724734],[-71.792767,41.807001],[-71.799242,42.008065],[-71.60620344113408,42.0131179102388],[-71.591096527631,42.013513343557186],[-71.559439,42.014342],[-71.49822401312468,42.01587411101849],[-71.45808099455608,42.01687882512869],[-71.381401,42.018798],[-71.38143134689308,41.985084119129496],[-71.381461,41.952141],[-71.3817,41.893199],[-71.339298,41.893399],[-71.339597,41.832],[-71.329396,41.7826],[-71.31726409756008,41.77719466337239],[-71.261392,41.752301],[-71.20860053289508,41.69030924360269],[-71.20132718752488,41.681768328202686],[-71.19564,41.67509],[-71.132888,41.660102],[-71.137492,41.602561],[-71.12057,41.497448],[-71.140224,41.485855],[-71.19302,41.457931],[-71.21267275910738,41.46660170590308],[-71.23980442381888,41.47857207017049],[-71.245992,41.481302],[-71.285639,41.487805],[-71.312694,41.451402],[-71.351096,41.450802],[-71.389284,41.460605],[-71.41721279148368,41.456031312774385],[-71.428652,41.454158],[-71.455371,41.407962],[-71.483295,41.371722],[-71.555381,41.373316],[-71.624505,41.36087],[-71.701631,41.336968],[-71.72929657620038,41.33328400271379],[-71.785957,41.325739],[-71.862772,41.309791],[-71.860513,41.320248]]]]}}, {"type":"Feature","properties":{"name":"Ohio","income":{"1995":33958,"1996":34198,"1997":36029,"1998":38726,"1999":39707,"2000":42054,"2001":41780,"2002":42246,"2003":43119,"2004":43371,"2005":43547,"2006":44609,"2007":46645,"2008":48011,"2009":45467,"2010":45151,"2011":45803,"2012":46873,"2013":48138,"2014":49349,"2015":51086}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-82.863342,41.693693],[-82.82572,41.72281],[-82.782719,41.694003],[-82.788876,41.643047],[-82.842099,41.628323],[-82.863342,41.693693]]],[[[-84.820159,39.227225],[-84.81887746927508,39.305143583559385],[-84.81887709781039,39.30516616905229],[-84.817453,39.391753],[-84.81616019491078,39.521968108992894],[-84.81570594325547,39.56772166402739],[-84.814129,39.726556],[-84.81412813793278,39.72661651161929],[-84.81141710638047,39.916913629579795],[-84.81016123847448,40.00506754384819],[-84.808706,40.107216],[-84.80491730257837,40.31009591503409],[-84.80412052701489,40.35276223029709],[-84.804119,40.352844],[-84.80293136657127,40.46538662171978],[-84.802547,40.50181],[-84.80241387857939,40.57221288064669],[-84.80211903226376,40.72814593687259],[-84.802119,40.728163],[-84.80267020615337,40.92256871392099],[-84.80285962195138,40.98937405200859],[-84.803234,41.121414],[-84.80364498225556,41.25256168354819],[-84.80370357261688,41.27125833057059],[-84.804133,41.408292],[-84.80425325761149,41.426049711549894],[-84.80495815623958,41.53013781338819],[-84.806082,41.696089],[-84.438067,41.704903],[-84.39954878547418,41.705921357405586],[-84.36041904139728,41.70695588263349],[-84.134417,41.712931],[-83.88039024525756,41.72019449661289],[-83.76314999206207,41.723546797762594],[-83.763038,41.72355],[-83.58554184210878,41.728772028512786],[-83.453832,41.732647],[-83.409531,41.691247],[-83.326825,41.701562],[-83.23166,41.644218],[-83.16382141752278,41.62413031297399],[-83.066593,41.59534],[-83.028072,41.555656],[-82.934369,41.514353],[-82.859531,41.576371],[-82.834101,41.587587],[-82.717878,41.54193],[-82.69056716066488,41.49670579543819],[-82.687921,41.492324],[-82.616952,41.428425],[-82.533208,41.391157],[-82.460599,41.386316],[-82.361784,41.426644],[-82.34801920689118,41.42726330873448],[-82.268479,41.430842],[-82.181598,41.471634],[-82.0711504528736,41.49691198678469],[-81.994565,41.51444],[-81.96848070252899,41.50386100790178],[-81.96032497000388,41.500553292597786],[-81.937862,41.491443],[-81.82250357969939,41.49525941928938],[-81.810758,41.495648],[-81.76857514162157,41.491489646476296],[-81.738755,41.48855],[-81.633652,41.540458],[-81.488682733409,41.63446392782089],[-81.466038,41.649148],[-81.388632,41.707144],[-81.286925,41.760243],[-81.184368,41.786671],[-81.05192,41.839557],[-81.00226940651747,41.84917246643759],[-80.900342,41.868912],[-80.800794,41.909635],[-80.581882,41.95761],[-80.519425,41.977523],[-80.51939672669049,41.84956299055929],[-80.519357,41.669767],[-80.51917675035338,41.499924051205994],[-80.51916516989557,41.48901219015458],[-80.51900013136428,41.33350214419358],[-80.518893,41.232556],[-80.51919669032499,41.133386502548895],[-80.51922208608089,41.12509356679578],[-80.51964377254728,40.987392654005795],[-80.519891,40.906661],[-80.51987684674039,40.90244867541969],[-80.51986970768618,40.900323934248895],[-80.51970511259918,40.851336778685386],[-80.518991,40.638801],[-80.583633,40.61552],[-80.627171,40.619936],[-80.667957,40.582496],[-80.622195,40.520497],[-80.604895,40.446667],[-80.62736262993687,40.395170933017184],[-80.631596,40.385468],[-80.606596,40.303869],[-80.644598,40.25127],[-80.68417321070798,40.18701797335069],[-80.70257530362257,40.157141398009685],[-80.705994,40.151591],[-80.736804,40.080072],[-80.73821843998358,40.033543226078386],[-80.740126,39.970793],[-80.764479,39.95025],[-80.803394,39.918762],[-80.82343810478588,39.85003208739639],[-80.824276,39.847159],[-80.824969,39.801092],[-80.869933,39.763555],[-80.83552169300748,39.71925180220009],[-80.829764,39.711839],[-80.865575,39.662751],[-80.943782,39.606926],[-81.03736504198706,39.538055712472584],[-81.07595,39.50966],[-81.12127385610779,39.45769741388929],[-81.128533,39.449375],[-81.185946,39.430731],[-81.249088,39.389992],[-81.347567,39.34577],[-81.37038980882629,39.348700672403396],[-81.393794,39.351706],[-81.412706,39.394618],[-81.456143,39.409274],[-81.503189,39.373242],[-81.559647,39.330774],[-81.565247,39.276175],[-81.613896,39.275339],[-81.678331,39.273755],[-81.711628,39.219228],[-81.72146813917249,39.210960809203684],[-81.752754,39.184676],[-81.75229703674009,39.18103474740589],[-81.742953,39.106578],[-81.75026684342629,39.10403119309979],[-81.807855,39.083978],[-81.793304,39.040353],[-81.775734,38.980737],[-81.827354,38.945898],[-81.89847,38.929603],[-81.941829,38.993295],[-82.007062,39.029578],[-82.041563,39.017878],[-82.089065,38.975978],[-82.09886665055427,38.96087928449329],[-82.134766,38.905579],[-82.16157,38.824632],[-82.20929,38.802672],[-82.201537,38.760372],[-82.185567,38.659583],[-82.175167,38.608484],[-82.218967,38.591683],[-82.27427,38.593683],[-82.28213334402808,38.57986079640348],[-82.293271,38.560283],[-82.304223,38.496308],[-82.323999,38.449268],[-82.381773,38.434783],[-82.447076,38.426982],[-82.50896694973129,38.414643912651684],[-82.560664,38.404338],[-82.593673,38.421809],[-82.618474,38.477089],[-82.66411690751568,38.50771559025699],[-82.675724,38.515504],[-82.724846,38.5576],[-82.800112,38.563183],[-82.8115423846504,38.57236958956188],[-82.851314,38.604334],[-82.869592,38.678177],[-82.871192,38.718377],[-82.88228999360929,38.741619223269595],[-82.889193,38.756076],[-82.943147,38.74328],[-83.011816,38.730057],[-83.03033493123107,38.71686767665609],[-83.042338,38.708319],[-83.112372,38.671685],[-83.128973,38.640231],[-83.172647,38.620252],[-83.239515,38.628588],[-83.26429890195868,38.613112496887496],[-83.286514,38.599241],[-83.320531,38.622713],[-83.376302,38.661473],[-83.440404,38.669361],[-83.533339,38.702105],[-83.626922,38.679387],[-83.642994,38.643273],[-83.64691140412668,38.641851934545784],[-83.679484,38.630036],[-83.70586163558556,38.63803786506599],[-83.77216,38.65815],[-83.78362,38.695641],[-83.834015,38.716008],[-83.852085,38.751433],[-83.90437508610479,38.76728387526779],[-83.928454,38.774583],[-83.978814,38.787104],[-84.051642,38.771397],[-84.05264617321959,38.77161466753579],[-84.135088,38.789485],[-84.212904,38.805707],[-84.22616263396347,38.829777141242],[-84.233265,38.842671],[-84.23230504540348,38.874707896031694],[-84.232132,38.880483],[-84.288164,38.955789],[-84.297255,38.989694],[-84.32120722685679,39.020586352689385],[-84.326539,39.027463],[-84.40094,39.046362],[-84.432941,39.083961],[-84.445242,39.114461],[-84.462042,39.12176],[-84.480943,39.11676],[-84.493743,39.10246],[-84.49918784070238,39.10216440086548],[-84.50651873743688,39.10176640818799],[-84.550844,39.09936],[-84.607928,39.073238],[-84.62228392463076,39.07842004166409],[-84.677247,39.09826],[-84.714048,39.132659],[-84.750749,39.147358],[-84.820157,39.10548],[-84.820159,39.227225]]]]}}, {"type":"Feature","properties":{"name":"Oklahoma","income":{"1995":26495,"1996":27648,"1997":30002,"1998":32373,"1999":33005,"2000":33417,"2001":34912,"2002":35313,"2003":35634,"2004":37109,"2005":37020,"2006":38753,"2007":41551,"2008":42836,"2009":41716,"2010":42076,"2011":43232,"2012":44336,"2013":45724,"2014":47524,"2015":48595}},"geometry":{"type":"Polygon","coordinates":[[[-103.002518,36.675186],[-103.001964,36.909573],[-103.002199,37.000104],[-102.841989,36.999598],[-102.698142,36.995149],[-102.355288,36.994506],[-102.04224,36.993083],[-102.02820419104496,36.993145147108294],[-101.90244,36.993702],[-101.55525884869098,36.99529093927759],[-101.485326,36.995611],[-101.211486,36.997124],[-101.06645021565997,36.99773617514039],[-100.945466793078,36.99824682872879],[-100.855634,36.998626],[-100.63332498615797,37.00017360905289],[-100.552683,37.000735],[-100.08948174390297,37.00147946946349],[-100.00257151432197,37.001619153911996],[-99.995201,37.001631],[-99.657658,37.000197],[-99.54111491236087,36.99990964456549],[-99.45620243467526,36.99970027940789],[-99.407015,36.999579],[-99.129449,36.999422],[-99.00030105388416,36.99935809814439],[-98.791936,36.999255],[-98.54466197334888,36.99852424040059],[-98.354073,36.997961],[-98.34714877974467,36.99796920864959],[-98.11198518374576,36.99824799463529],[-98.045342,36.998327],[-97.80231297035029,36.99869860939399],[-97.768704,36.99875],[-97.46234602986407,36.99882423879689],[-97.384925,36.998843],[-97.14772096692268,36.99897233562149],[-97.100652,36.998998],[-96.749838,36.998988],[-96.52558204428287,36.99867796872479],[-96.500288,36.998643],[-96.217571,36.99907],[-96.00081020619957,36.999201052927894],[-95.96427123210216,36.999223144282396],[-95.928122,36.999245],[-95.78676187077816,36.99927091759199],[-95.573598,36.99931],[-95.52241455239867,36.99931978678289],[-95.40762000587706,36.99934173663909],[-95.322565,36.999358],[-95.07350396663027,36.99948813467909],[-95.00762000447206,36.99952255912579],[-94.995293,36.999529],[-94.71277,36.998794],[-94.617964,36.998905],[-94.618307,36.76656],[-94.61799177841718,36.66792127234419],[-94.617815,36.612604],[-94.617919,36.499414],[-94.5862,36.299969],[-94.56226800249247,36.16197304097529],[-94.55190628260627,36.10222560566859],[-94.532071,35.987852],[-94.494549,35.768303],[-94.49304007242698,35.759166474327294],[-94.47311939064667,35.63854715252939],[-94.449696,35.496719],[-94.43488928759668,35.39318521558748],[-94.43391344383237,35.38636176989869],[-94.431515,35.369591],[-94.435316,35.275893],[-94.44292586168999,35.06250620957269],[-94.44750953578428,34.93397621215719],[-94.449058,34.890556],[-94.45439503413786,34.72895867317939],[-94.4575,34.634945],[-94.46116868615587,34.50745665157249],[-94.465425,34.359548],[-94.47015267816208,34.189864292126096],[-94.474895,34.019655],[-94.47726674152977,33.94091092793479],[-94.481842,33.789008],[-94.485875,33.637867],[-94.528928,33.62184],[-94.572872,33.669886],[-94.630586,33.673401],[-94.714865,33.707261],[-94.73193290199589,33.720830516280294],[-94.766146,33.748031],[-94.841634,33.739431],[-94.902276,33.776289],[-94.93956,33.810503],[-94.98165,33.852284],[-95.046568,33.862565],[-95.095002,33.904816],[-95.149462,33.936336],[-95.15590761710747,33.93848238856979],[-95.226393,33.961954],[-95.253623,33.92971],[-95.283445,33.877746],[-95.31044979544906,33.87384303818549],[-95.352338,33.867789],[-95.44737,33.86885],[-95.525322,33.885487],[-95.556915,33.92702],[-95.603657,33.927195],[-95.669978,33.905844],[-95.737508,33.895967],[-95.78963931775226,33.87243738467229],[-95.820596,33.858465],[-95.84487853407067,33.86042190471899],[-95.887491,33.863856],[-95.935325,33.875099],[-96.063924,33.841523],[-96.15163,33.831946],[-96.173025,33.80056],[-96.229023,33.748021],[-96.277269,33.769735],[-96.307389,33.735005],[-96.363135,33.694215],[-96.37966082595207,33.715530908565995],[-96.403507,33.746289],[-96.436455,33.78005],[-96.502286,33.77346],[-96.523863,33.818114],[-96.572937,33.819098],[-96.592926,33.830916],[-96.590112,33.880665],[-96.59467430737708,33.883018657398296],[-96.659896,33.916666],[-96.682103,33.876645],[-96.712422,33.831633],[-96.776766,33.841976],[-96.794276,33.868886],[-96.850593,33.847211],[-96.897194,33.902954],[-96.905253,33.947219],[-96.93434330313298,33.94558892925279],[-96.94461688837048,33.945013250454],[-96.952313,33.944582],[-96.988745,33.918468],[-96.985567,33.886522],[-97.055838,33.855741],[-97.07859,33.812756],[-97.087852,33.774099],[-97.091072,33.735115],[-97.149394,33.721967],[-97.205652,33.809824],[-97.166629,33.847311],[-97.206141,33.91428],[-97.24618,33.900344],[-97.318243,33.865121],[-97.372941,33.819454],[-97.444193,33.823773],[-97.451469,33.87093],[-97.48414343858758,33.91388910889089],[-97.486505,33.916994],[-97.55827,33.897099],[-97.56124315022106,33.89906150673299],[-97.596155,33.922106],[-97.609091,33.968093],[-97.671772,33.99137],[-97.759834,33.92521],[-97.803473,33.88019],[-97.865765,33.849393],[-97.951215,33.878424],[-97.95190595085516,33.89122581485729],[-97.953695,33.924373],[-97.947572,33.991053],[-98.005667,33.995964],[-98.082839,34.002412],[-98.099096,34.048639],[-98.099328,34.104295],[-98.123377,34.15454],[-98.13848602574639,34.14120601971109],[-98.16912,34.114171],[-98.225282,34.127245],[-98.31875,34.146421],[-98.364023,34.157109],[-98.398441,34.128456],[-98.414426,34.085074],[-98.423533,34.081949476005896],[-98.475066,34.064269],[-98.5282,34.094961],[-98.577136,34.148962],[-98.61035178164467,34.15620993949669],[-98.648073,34.164441],[-98.690072,34.133155],[-98.737232,34.130992],[-98.80681,34.155901],[-98.872229,34.160446],[-98.94022,34.203686],[-98.95232488752816,34.20466989860349],[-99.002916,34.208782],[-99.0588,34.201256],[-99.131553,34.209352],[-99.189511,34.214312],[-99.2116,34.31397],[-99.22160790084548,34.32537357437259],[-99.27534,34.386599],[-99.350407,34.437083],[-99.394956,34.442099],[-99.420432,34.380464],[-99.470969,34.396471],[-99.47502213703837,34.39687098979049],[-99.58448,34.407673],[-99.600026,34.374688],[-99.696462,34.381036],[-99.764882,34.435266],[-99.818186,34.48784],[-99.84206388414638,34.50693276888139],[-99.929334,34.576714],[-99.99762932816299,34.56113662456009],[-100.000381,34.560509],[-100.000382194816,34.74636055256159],[-100.00038402077298,35.03038499999989],[-100.000385,35.182702],[-100.00038884414299,35.42236398830939],[-100.000392,35.619115],[-100.00039619832899,35.880947999996785],[-100.000399,36.055677],[-100.000406,36.499702],[-100.00376199336799,36.499701848737594],[-100.311018,36.499688],[-100.54614512609699,36.49950513930379],[-100.592614,36.499469],[-100.884174,36.499682],[-100.95415215769299,36.49952949662619],[-101.085156,36.499244],[-101.623915,36.499528],[-101.826565,36.499654],[-102.03233901896297,36.50006567301009],[-102.162463,36.500326],[-103.002434,36.500397],[-103.002188,36.602716],[-103.002518,36.675186]]]}}, {"type":"Feature","properties":{"name":"South Carolina","income":{"1995":30060,"1996":32728,"1997":33325,"1998":33465,"1999":35515,"2000":37283,"2001":36953,"2002":37442,"2003":38003,"2004":39454,"2005":39477,"2006":41204,"2007":43508,"2008":44695,"2009":42580,"2010":42117,"2011":42477,"2012":43290,"2013":44310,"2014":45337,"2015":47308}},"geometry":{"type":"Polygon","coordinates":[[[-83.353238,34.728648],[-83.320062,34.759616],[-83.323866,34.789712],[-83.284812,34.823043],[-83.252582,34.853483],[-83.201183,34.884653],[-83.140621,34.924915],[-83.124378,34.95524],[-83.108606,35.000659],[-83.00843480376807,35.02692851150739],[-82.897499,35.056021],[-82.783283,35.0856],[-82.76205955211358,35.08187443600409],[-82.746431,35.079131],[-82.68604,35.124545],[-82.57771554495088,35.14647526757419],[-82.53256,35.155617],[-82.455609,35.177425],[-82.411301,35.202483],[-82.35302152309048,35.19870416046639],[-82.295354,35.194965],[-82.21624871922907,35.19325854865318],[-82.04839122964786,35.18963754337549],[-82.039651,35.189449],[-81.96935840125757,35.18692708840049],[-81.87411220431628,35.183509908026295],[-81.76806906135857,35.17970536192819],[-81.494265,35.169882],[-81.36760858859688,35.16409232932819],[-81.3280909892918,35.16228591555739],[-81.04287,35.149248],[-81.04226581176299,35.146608594145796],[-81.036759,35.122552],[-81.058029,35.07319],[-81.041489,35.044703],[-80.93495,35.107409],[-80.90623995408248,35.07518426976559],[-80.90348118671209,35.07208777404609],[-80.84056591565317,35.00147041441789],[-80.782042,34.935782],[-80.796997,34.823874],[-80.56167339135038,34.817481445270296],[-80.561657,34.817481],[-80.32083257112978,34.81362082154399],[-80.077223,34.809716],[-79.92810346909137,34.80787131715529],[-79.92468425313638,34.807829019751495],[-79.69294834227739,34.80496233115169],[-79.675299,34.804744],[-79.46196554440178,34.63017348270309],[-79.45027745772619,34.6206091350416],[-79.358317,34.545358],[-79.071169,34.29924],[-78.81171,34.081006],[-78.65088747609119,33.94506940996439],[-78.615932,33.915523],[-78.541087,33.851112],[-78.67226,33.817587],[-78.772737,33.768511],[-78.862931,33.705654],[-78.938076,33.639826],[-78.99563169438349,33.572074598189296],[-79.028516,33.533365],[-79.084588,33.483669],[-79.135441,33.403867],[-79.162332,33.327246],[-79.180563,33.237955],[-79.172394,33.206577],[-79.215453,33.155569],[-79.27449458464278,33.12005626772039],[-79.291591,33.109773],[-79.329909,33.089986],[-79.339313,33.050336],[-79.359961,33.006672],[-79.423447,33.015085],[-79.483499,33.001265],[-79.522449,33.03535],[-79.580725,33.006447],[-79.606615,32.972248],[-79.569762,32.926692],[-79.601309,32.89815],[-79.695141,32.850398],[-79.726389,32.805996],[-79.818237,32.766352],[-79.868352,32.734849],[-79.884961,32.684402],[-79.968468,32.639732],[-80.000801,32.605892],[-80.077039,32.603319],[-80.148406,32.578479],[-80.190108,32.546841],[-80.246361,32.531114],[-80.24944242622779,32.52935932919329],[-80.338354,32.47873],[-80.40327659277136,32.47220240740669],[-80.413505,32.471174],[-80.46571,32.4953],[-80.46911077375938,32.48912619355169],[-80.47136206778757,32.48503916672449],[-80.47229312469508,32.48334891458009],[-80.484617,32.460976],[-80.457502,32.410264],[-80.434303,32.375193],[-80.455192,32.326458],[-80.539429,32.287024],[-80.596394,32.273549],[-80.644794,32.291497],[-80.714601,32.325656],[-80.766038,32.292608],[-80.726967,32.265706],[-80.669166,32.216783],[-80.721463,32.160427],[-80.812503,32.109746],[-80.858735,32.099581],[-80.86742768189158,32.07849],[-80.885517,32.0346],[-80.943226,32.057824],[-81.006745,32.101152],[-81.038265,32.084469],[-81.113334,32.113205],[-81.119361,32.177142],[-81.14759517045536,32.22716944659709],[-81.153531,32.237687],[-81.128034,32.276297],[-81.133032,32.334794],[-81.17347379448609,32.38490278088669],[-81.194931,32.411489],[-81.194829,32.465086],[-81.274927,32.544158],[-81.28423838176558,32.547110946284995],[-81.328753,32.561228],[-81.38690190269416,32.59896485389979],[-81.397106,32.605587],[-81.393818,32.653491],[-81.41267,32.739083],[-81.4131167951736,32.744261327961496],[-81.42062,32.831223],[-81.464069,32.897814],[-81.499566,32.943722],[-81.50203,33.015113],[-81.54396622431388,33.04439995414439],[-81.601655,33.084688],[-81.61595571078908,33.08933853936399],[-81.658433,33.103152],[-81.755135,33.15155],[-81.76250598279576,33.197265888297295],[-81.763535,33.203648],[-81.846536,33.241746],[-81.84650053235788,33.24725208542989],[-81.846136,33.303843],[-81.932737,33.343541],[-81.920121,33.410753],[-81.926336,33.462937],[-81.990938,33.494235],[-82.01655587044488,33.529055386425895],[-82.028238,33.544934],[-82.10624,33.595637],[-82.11465383858477,33.59790505457],[-82.14245647450088,33.60539959999209],[-82.161908,33.610643],[-82.199747,33.657611],[-82.21593836474749,33.68775497531869],[-82.239098,33.730872],[-82.32448,33.820033],[-82.43115,33.867051],[-82.51295,33.936969],[-82.556835,33.945353],[-82.56299679858088,33.95655491052689],[-82.591855,34.009018],[-82.59502579260727,34.013517809209596],[-82.642797,34.081312],[-82.715373,34.148165],[-82.73510798894158,34.21261481224289],[-82.744982,34.244861],[-82.77462873101207,34.28836681825469],[-82.780308,34.296701],[-82.82342,34.358872],[-82.841997,34.399766],[-82.873831,34.471508],[-82.925766,34.481802],[-82.99138815318229,34.47298062723579],[-82.99509,34.472483],[-83.048289,34.493254],[-83.05057296410239,34.49505365216909],[-83.096858,34.531524],[-83.10287382603569,34.53743090976538],[-83.154577,34.588198],[-83.221402,34.609947],[-83.27796,34.644853],[-83.33869,34.682002],[-83.34003910678457,34.686327710412094],[-83.34960851091326,34.71701058262729],[-83.353238,34.728648]]]}}, {"type":"Feature","properties":{"name":"Colorado","income":{"1995":37235,"1996":38923,"1997":40853,"1998":43402,"1999":45557,"2000":47505,"2001":48483,"2002":48060,"2003":49248,"2004":50105,"2005":50841,"2006":52265,"2007":55517,"2008":57184,"2009":55735,"2010":54411,"2011":55530,"2012":56880,"2013":58942,"2014":61324,"2015":63945}},"geometry":{"type":"Polygon","coordinates":[[[-109.059962,38.499987],[-109.05996197258898,38.49998903102078],[-109.051512,39.126095],[-109.051223831017,39.36667754958628],[-109.05106684627299,39.49773880936619],[-109.05087192526199,39.660471777159394],[-109.050615,39.87497],[-109.050973,40.180849],[-109.05073211207697,40.22265525825759],[-109.048249,40.653601],[-109.04825975004798,40.66260181722799],[-109.048455,40.826081],[-109.050076,41.000659],[-108.250649,41.000114],[-107.91841828984899,41.00122707064409],[-107.367443,41.003073],[-107.31779575978997,41.00284248123219],[-106.86037794866498,41.00071862923709],[-106.32116921591397,40.99821501106799],[-106.217573,40.997734],[-106.19055407870897,40.99774661257439],[-105.277138,40.998173],[-105.276859994035,40.99817291762589],[-104.943371,40.99807410372979],[-104.855273,40.998048],[-104.497058,41.001805],[-104.053249,41.001406],[-103.574522,41.001721],[-103.573774006195,41.00172179908409],[-103.38249165188998,41.001926146620995],[-103.076536,41.002253],[-102.65346413726898,41.00222532414359],[-102.62103302445198,41.002223202615596],[-102.556789,41.002219],[-102.05171751637799,41.00237696762389],[-102.051614,41.002377],[-102.051292,40.749591],[-102.05129200020698,40.74958599487369],[-102.05129415157899,40.697546832388994],[-102.05130479859699,40.44000799337699],[-102.05130855184399,40.34922135687219],[-102.051309,40.338381],[-102.051744,40.003078],[-102.051254,39.818992],[-102.04999213564399,39.574056097421],[-102.04996185782798,39.56817898067309],[-102.04896,39.373712],[-102.04720072170099,39.13314670951119],[-102.046571,39.047038],[-102.04571290308698,38.69756577007849],[-102.04551057456999,38.61516459017749],[-102.044944,38.384419],[-102.04465035914698,38.26874922250309],[-102.04463427029097,38.262411567749496],[-102.044255,38.113011],[-102.04196565862797,37.73854057363819],[-102.041876,37.723875],[-102.04189086966498,37.64427768529179],[-102.04193852287398,37.38919005539379],[-102.041963,37.258164],[-102.041983,37.106551],[-102.04192,37.035083],[-102.04224,36.993083],[-102.355288,36.994506],[-102.698142,36.995149],[-102.841989,36.999598],[-103.002199,37.000104],[-103.08610107563098,36.99986436110639],[-103.733247,36.998016],[-104.00784940961297,36.995984094709094],[-104.338833,36.993535],[-104.732031,36.993447],[-105.1208,36.995428],[-105.15504274804798,36.9954744456106],[-105.22050520078098,36.99556323648649],[-105.251296,36.995605],[-105.41931,36.995856],[-105.533922,36.995875],[-105.716471,36.995849],[-105.71846968399099,36.995845927301],[-105.997472,36.995417],[-106.00631641079798,36.995386628817286],[-106.343139,36.99423],[-106.476233588828,36.99377410054689],[-106.869796,36.992426],[-106.877292,37.000139],[-107.420913,37.000005],[-107.42092190574498,37.00000499993859],[-107.48173699915498,37.00000458031429],[-108.000623,37.000001],[-108.37930295009397,36.999564686311494],[-108.620309,36.999287],[-109.045223,36.999084],[-109.04378072050297,37.48481923141749],[-109.04260410062098,37.881084817492585],[-109.04179661485499,38.15303230496849],[-109.041762,38.16469],[-109.060062,38.275489],[-109.059962,38.499987]]]}}, {"type":"Feature","properties":{"name":"Kansas","income":{"1995":32114,"1996":33610,"1997":36488,"1998":38553,"1999":39726,"2000":41150,"2001":42081,"2002":42104,"2003":43113,"2004":41664,"2005":42861,"2006":45369,"2007":47341,"2008":50174,"2009":47709,"2010":47888,"2011":48844,"2012":50140,"2013":50892,"2014":52392,"2015":53802}},"geometry":{"type":"Polygon","coordinates":[[[-102.051744,40.003078],[-101.832161,40.002933],[-101.542273,40.002609],[-101.41102898780197,40.002582569567586],[-101.32551402751898,40.00256534823049],[-101.293991,40.002559],[-101.060317,40.002307],[-100.75883,40.002302],[-100.73882471319098,40.002262956567684],[-100.477018,40.001752],[-100.19359905683599,40.00157300571989],[-100.19359,40.001573],[-100.17779754587897,40.00156581385159],[-99.813401,40.0014],[-99.62825384922449,40.00177194726839],[-99.62532672639958,40.00177782764698],[-99.501792,40.002026],[-99.17913315086108,40.00210895269489],[-99.085597,40.002133],[-99.06701834989808,40.00214351305219],[-98.72637296393899,40.00233627316689],[-98.613755,40.0024],[-98.50445498363678,40.002379876736],[-98.27401705975288,40.00233745072989],[-98.076034,40.002301],[-97.93182492631716,40.00223634501959],[-97.82150081227518,40.002186882088886],[-97.777155,40.002167],[-97.415833,40.002001],[-97.36919903531498,40.00193930576049],[-97.009165,40.001463],[-96.91640700546577,40.00145409104389],[-96.873812,40.00145],[-96.805768,40.001368455095395],[-96.469945,40.000966],[-96.46371207677477,40.00095857255448],[-96.23920787841108,40.00069104275439],[-96.239172,40.000691],[-96.154365,40.000495],[-96.02409,40.000719],[-96.01067881793449,40.00070466577199],[-95.78811099489167,40.00046677936529],[-95.784575,40.000463],[-95.33989597085028,40.00002885710539],[-95.30829,39.999998],[-95.231114,39.943784],[-95.142445,39.89542],[-95.081534,39.861718],[-95.018743,39.897372],[-94.99337423971437,39.89856525999229],[-94.95154,39.900533],[-94.928466,39.876344],[-94.878677,39.826522],[-94.87781752985117,39.82041477603549],[-94.871144,39.772994],[-94.860371,39.74953],[-94.899316,39.724042],[-94.971078,39.723146],[-94.971317,39.68641],[-95.037464,39.652905],[-95.04405075257039,39.61366829682089],[-95.047165,39.595117],[-95.076688,39.576764],[-95.113557,39.553941],[-95.09141940282399,39.53325788520999],[-95.049845,39.494415],[-94.982144,39.440552],[-94.96574741863347,39.42168174465639],[-94.946662,39.399717],[-94.888972,39.392432],[-94.908065,39.323663],[-94.857072,39.273825],[-94.825663,39.241729],[-94.799663,39.206018],[-94.79199467374328,39.20126025024019],[-94.741938,39.170203],[-94.680336,39.184303],[-94.623934,39.156603],[-94.60193798192108,39.15550323346379],[-94.591933,39.155003],[-94.607354,39.113444],[-94.60787035337397,39.04408509647849],[-94.608334,38.981806],[-94.60896034374949,38.84721131544499],[-94.609456,38.7407],[-94.60948967234579,38.73810170947319],[-94.61195801832227,38.547634434271686],[-94.61286559592209,38.47760218023509],[-94.612866,38.477571],[-94.61277262899287,38.38871848273179],[-94.612614,38.237766],[-94.61392996105577,38.06005295989649],[-94.61410024870548,38.03705658338129],[-94.614465,37.987799],[-94.617885,37.682214],[-94.61787245089806,37.673110700332096],[-94.6178455243542,37.653577796634394],[-94.617511,37.410909],[-94.61766760470077,37.36417032703869],[-94.61775389160657,37.338418],[-94.618351,37.160211],[-94.61810289110298,37.05679639087289],[-94.617964,36.998905],[-94.71277,36.998794],[-94.995293,36.999529],[-95.00762000447206,36.99952255912579],[-95.07350396663027,36.99948813467909],[-95.322565,36.999358],[-95.40762000587706,36.99934173663909],[-95.52241455239867,36.99931978678289],[-95.573598,36.99931],[-95.78676187077816,36.99927091759199],[-95.928122,36.999245],[-95.96427123210216,36.999223144282396],[-96.00081020619957,36.999201052927894],[-96.217571,36.99907],[-96.500288,36.998643],[-96.52558204428287,36.99867796872479],[-96.749838,36.998988],[-97.100652,36.998998],[-97.14772096692268,36.99897233562149],[-97.384925,36.998843],[-97.46234602986407,36.99882423879689],[-97.768704,36.99875],[-97.80231297035029,36.99869860939399],[-98.045342,36.998327],[-98.11198518374576,36.99824799463529],[-98.34714877974467,36.99796920864959],[-98.354073,36.997961],[-98.54466197334888,36.99852424040059],[-98.791936,36.999255],[-99.00030105388416,36.99935809814439],[-99.129449,36.999422],[-99.407015,36.999579],[-99.45620243467526,36.99970027940789],[-99.54111491236087,36.99990964456549],[-99.657658,37.000197],[-99.995201,37.001631],[-100.00257151432197,37.001619153911996],[-100.08948174390297,37.00147946946349],[-100.552683,37.000735],[-100.63332498615797,37.00017360905289],[-100.855634,36.998626],[-100.945466793078,36.99824682872879],[-101.06645021565997,36.99773617514039],[-101.211486,36.997124],[-101.485326,36.995611],[-101.55525884869098,36.99529093927759],[-101.90244,36.993702],[-102.02820419104496,36.993145147108294],[-102.04224,36.993083],[-102.04192,37.035083],[-102.041983,37.106551],[-102.041963,37.258164],[-102.04193852287398,37.38919005539379],[-102.04189086966498,37.64427768529179],[-102.041876,37.723875],[-102.04196565862797,37.73854057363819],[-102.044255,38.113011],[-102.04463427029097,38.262411567749496],[-102.04465035914698,38.26874922250309],[-102.044944,38.384419],[-102.04551057456999,38.61516459017749],[-102.04571290308698,38.69756577007849],[-102.046571,39.047038],[-102.04720072170099,39.13314670951119],[-102.04896,39.373712],[-102.04996185782798,39.56817898067309],[-102.04999213564399,39.574056097421],[-102.051254,39.818992],[-102.051744,40.003078]]]}}, {"type":"Feature","properties":{"name":"Connecticut","income":{"1995":43274,"1996":44981,"1997":46648,"1998":49846,"1999":51706,"2000":52758,"2001":55060,"2002":54543,"2003":56409,"2004":56617,"2005":60840,"2006":63352,"2007":65969,"2008":68294,"2009":66906,"2010":64321,"2011":65822,"2012":67275,"2013":67262,"2014":70007,"2015":71333}},"geometry":{"type":"Polygon","coordinates":[[[-73.69593580216956,41.11525545690408],[-73.482709,41.21276],[-73.550961,41.295422],[-73.54415118640058,41.36631959624439],[-73.54330658069169,41.375112864027685],[-73.54318320799626,41.376397308516786],[-73.54314734626546,41.37677066829739],[-73.536969,41.441094],[-73.52967771430127,41.527161021128286],[-73.520017,41.641197],[-73.51791879063818,41.666720530709995],[-73.505008,41.823773],[-73.487314,42.049638],[-73.231056,42.044945],[-73.12722917087838,42.04212314835478],[-73.05336267374808,42.040115571910285],[-73.00876278163068,42.03890341624669],[-72.999549,42.038653],[-72.847142,42.036894],[-72.810078,41.998316],[-72.77475931607859,42.00212910418029],[-72.766739,42.002995],[-72.735496,42.036399],[-72.607933,42.030795],[-72.528131,42.034295],[-72.50917933629829,42.03408049659008],[-72.39747625519588,42.03281619113578],[-72.317148,42.031907],[-72.19884597813198,42.030103893281996],[-72.13573146194668,42.02914192994159],[-72.10215943452678,42.028630240054795],[-71.987326,42.02688],[-71.88467683590369,42.025059351484295],[-71.80065,42.023569],[-71.799242,42.008065],[-71.792767,41.807001],[-71.789678,41.724734],[-71.78967758183198,41.724568000295285],[-71.78946459083899,41.64001719070689],[-71.789356,41.59691],[-71.78935867274228,41.59685216034269],[-71.79171906174719,41.54577200433499],[-71.797683,41.416709],[-71.839649,41.412119],[-71.835951,41.353935],[-71.860513,41.320248],[-71.886302,41.33641],[-71.956747,41.329871],[-72.021898,41.316838],[-72.094443,41.314164],[-72.134221,41.299398],[-72.201422,41.315697],[-72.235531,41.300413],[-72.293044,41.280044],[-72.3400129087019,41.277849262238384],[-72.348643,41.277446],[-72.386629,41.261798],[-72.40593,41.278398],[-72.472539,41.270103],[-72.5345648971681,41.25382427439109],[-72.547235,41.250499],[-72.598036,41.268698],[-72.653838,41.265897],[-72.65435402015119,41.26562630830019],[-72.690439,41.246697],[-72.760341,41.241235],[-72.786142,41.264796],[-72.881445,41.242597],[-72.90393376006288,41.24919413446249],[-72.935646,41.258497],[-72.97050541549919,41.24127430899629],[-72.98484081275468,41.23419174281399],[-72.986247,41.233497],[-73.020449,41.206397],[-73.07945,41.194015],[-73.1011738216445,41.163726271164286],[-73.108352,41.153718],[-73.130253,41.146797],[-73.17283536512738,41.15344227911238],[-73.202656,41.158096],[-73.262358,41.117496],[-73.26981757976849,41.116676890043294],[-73.297214389349,41.11366854370119],[-73.33066,41.109996],[-73.372296,41.10402],[-73.354231,41.085639],[-73.387227,41.058247],[-73.422165,41.047562],[-73.468239,41.051347],[-73.516903,41.038738],[-73.561968,41.016797],[-73.595699,41.015995],[-73.657336,40.985171],[-73.65737400926137,40.98552488385919],[-73.659362,41.004034],[-73.659533,41.017857],[-73.727775,41.100696],[-73.69593580216956,41.11525545690408]]]}}, {"type":"Feature","properties":{"name":"Nevada","income":{"1995":36300,"1996":38213,"1997":39280,"1998":39867,"1999":41939,"2000":44698,"2001":44325,"2002":44560,"2003":45249,"2004":47231,"2005":49288,"2006":52800,"2007":54996,"2008":56432,"2009":53310,"2010":50987,"2011":49099,"2012":49909,"2013":51250,"2014":51487,"2015":52544}},"geometry":{"type":"Polygon","coordinates":[[[-120.00479551230397,39.31647501195848],[-120.00302891965698,39.44504577616049],[-120.00174,39.538852],[-119.99993544808497,39.72240692472418],[-119.997634,39.956505],[-119.997124,40.126363],[-119.996155,40.32125],[-119.997533,40.720992],[-119.999231,40.865899],[-119.999866,41.183974],[-119.99828,41.618765],[-119.999276,41.874891],[-119.999168,41.99454],[-119.72573,41.996296],[-119.36012311960299,41.99409225498119],[-119.32418412043896,41.99387562779329],[-119.20828,41.993177],[-119.001022,41.993793],[-118.775869,41.992692],[-118.501002,41.995446],[-118.19736921592799,41.996994081163486],[-118.197189,41.996995],[-117.873467,41.998335],[-117.623731,41.998467],[-117.403613,41.99929],[-117.197798,42.00038],[-117.026197,41.99989],[-117.018203216741,41.99983985036909],[-116.625947,41.997379],[-116.332763,41.997283],[-115.870181,41.996766],[-115.625914,41.997415],[-115.313877,41.996103],[-115.03810975243397,41.99863411567649],[-114.89921,41.999909],[-114.598267,41.994511],[-114.281855,41.994214],[-114.28179946721997,41.99421388575789],[-114.041723,41.99372],[-114.039901,41.753781],[-114.040231,41.49169],[-114.041447,41.207752],[-114.042145,40.999926],[-114.04214514623497,40.999896577263286],[-114.043505,40.726292],[-114.045577,40.495801],[-114.046178,40.398313],[-114.04637281737297,40.116935833012185],[-114.046386,40.097896],[-114.04726815307697,39.906098113756194],[-114.047783,39.79416],[-114.04718141292597,39.54274360222969],[-114.047079,39.499943],[-114.049104,39.005509],[-114.048054,38.878693],[-114.04943670593099,38.677362456879585],[-114.05015362080597,38.57297521300339],[-114.050154,38.57292],[-114.05012,38.404536],[-114.050138,38.24996],[-114.04990337565798,38.148763026670586],[-114.049903,38.148601],[-114.049658,37.881368],[-114.051728,37.745997],[-114.05247199661397,37.60477664271939],[-114.052472,37.604776],[-114.052701,37.492014],[-114.051974,37.284511],[-114.051749,37.088434],[-114.0506,37.000396],[-114.05016077608799,36.84314153968939],[-114.049493,36.604059],[-114.047584,36.325573],[-114.048226,36.268874],[-114.046838,36.194069],[-114.09987,36.121654],[-114.138203,36.053161],[-114.151725,36.024563],[-114.21369,36.015613],[-114.270645,36.03572],[-114.316109,36.063109],[-114.337273,36.10802],[-114.372106,36.143114],[-114.41695,36.145761],[-114.448654,36.12641],[-114.487034,36.129396],[-114.511721,36.150956],[-114.572031,36.15161],[-114.627855,36.141012],[-114.666538,36.117343],[-114.736165,36.104367],[-114.743342,36.070535],[-114.74329924588599,36.06593517376009],[-114.742779,36.009963],[-114.731159,35.943916],[-114.700271,35.901772],[-114.669687,35.865084],[-114.70371,35.814585],[-114.697309,35.733686],[-114.689407,35.651412],[-114.653406,35.610789],[-114.663105,35.524491],[-114.6645,35.449497],[-114.627137,35.409504],[-114.587129,35.262376],[-114.572747,35.138725],[-114.59912,35.12105],[-114.619905,35.121632],[-114.625069,35.068478],[-114.633487,35.001857],[-114.804249,35.139689],[-115.043812,35.332012],[-115.160068,35.424129],[-115.303743,35.538207],[-115.404537,35.617605],[-115.647683,35.809358],[-115.64803201962498,35.80962921260289],[-115.84611392276199,35.96355267311089],[-115.892975,35.999967],[-116.093601,36.155805],[-116.375875,36.372562],[-116.488233,36.459097],[-117.000895,36.847694],[-117.166000564031,36.97120753859029],[-117.244917,37.030244],[-117.68061,37.353399],[-117.83350404414396,37.46493876624449],[-118.022181,37.602583],[-118.42799532515699,37.896224280909784],[-118.500958,37.949019],[-118.949673,38.26894],[-119.157226100872,38.41439197176128],[-119.279262,38.499914],[-119.32870452107596,38.534351927797495],[-119.58540614483898,38.713150900671195],[-119.587679,38.714734],[-119.904315,38.933324],[-120.001014,38.999574],[-120.00197525086698,39.06749587446829],[-120.00261484291299,39.11268937409578],[-120.00336402883298,39.16562676406879],[-120.005142,39.291258],[-120.00479551230397,39.31647501195848]]]}}, {"type":"Feature","properties":{"name":"Washington","income":{"1995":37015,"1996":37847,"1997":41715,"1998":44307,"1999":44742,"2000":44846,"2001":46284,"2002":46399,"2003":48185,"2004":48438,"2005":49372,"2006":52571,"2007":55628,"2008":58081,"2009":56479,"2010":55584,"2011":56811,"2012":57574,"2013":58431,"2014":61358,"2015":64080}},"geometry":{"type":"MultiPolygon","coordinates":[[[[-123.237148,48.683466],[-123.070427,48.699971],[-123.019699,48.721312],[-122.979519,48.781702],[-122.937925,48.790315],[-122.818436,48.744629],[-122.743049,48.661991],[-122.79901,48.604683],[-122.771206,48.562426],[-122.779124,48.508911],[-122.817912,48.483888],[-122.803521,48.428748],[-122.874135,48.418196],[-122.928004,48.439966],[-123.039156,48.460003],[-123.141478,48.505291],[-123.20268,48.590214],[-123.237148,48.683466]]],[[[-124.725839,48.386012],[-124.653243,48.390691],[-124.546259,48.353594],[-124.380874,48.284699],[-124.250882,48.264773],[-124.101773,48.216883],[-124.050734,48.177747],[-123.880068,48.160621],[-123.728736,48.1628],[-123.672445,48.162715],[-123.551131,48.151382],[-123.441972,48.124259],[-123.314578,48.113725],[-123.239129,48.118217],[-123.144783,48.175943],[-123.06621,48.120469],[-123.004128,48.090516],[-122.946119,48.098552],[-122.91068675572495,48.10979974393279],[-122.833173,48.134406],[-122.760448,48.14324],[-122.698465,48.103102],[-122.70184,48.016106],[-122.701294,47.972979],[-122.651063,47.920985],[-122.63410286527996,47.923035299738785],[-122.616701,47.925139],[-122.57374586431497,47.95100416720909],[-122.546824,47.967215],[-122.542924,47.996404],[-122.607342,48.030992],[-122.598301,48.110616],[-122.633167,48.163281],[-122.711508,48.193573],[-122.752563,48.260061],[-122.707077,48.315286],[-122.66698252821598,48.41246699204428],[-122.665338,48.416453],[-122.689121,48.476849],[-122.650307,48.530156],[-122.642597,48.588339],[-122.67134542566697,48.64529899852018],[-122.710177,48.722237],[-122.720045,48.789195],[-122.732506,48.838097],[-122.794018,48.88313],[-122.821631,48.941369],[-122.75802,49.002357],[-122.251063,49.002494],[-122.098357,49.002146],[-121.751252,48.997399],[-121.395543,48.999851],[-121.12624,49.001412],[-120.85152713301797,49.00059115283519],[-120.716604,49.000188],[-120.376216,49.000705],[-120.001199,48.999418],[-119.4577,49.000261],[-119.132102,49.000262],[-118.83661303557997,49.00030775929759],[-118.19737505245898,49.000406751424585],[-118.002046,49.000437],[-117.607323,49.000843],[-117.429968,49.00030686982558],[-117.268247,48.999818],[-117.032351,48.999188],[-117.03293918211699,48.84666792120148],[-117.033671,48.656902],[-117.035289,48.422732],[-117.041107,48.124904],[-117.04121445346098,48.04546510380278],[-117.04130644645898,47.97745592002679],[-117.041634,47.7353],[-117.04049037556798,47.36602888669798],[-117.04015975186299,47.259272],[-117.039836,47.154734],[-117.03983338602796,47.12726899225409],[-117.03977765556199,46.541708992038096],[-117.039771,46.471779],[-117.036645748421,46.426100482655386],[-117.035545,46.410012],[-117.062748,46.353624],[-116.99726,46.303151],[-116.964379,46.253282],[-116.962966,46.19968],[-116.923958,46.17092],[-116.935473,46.142448],[-116.981962,46.084915],[-116.942656,46.061],[-116.915989,45.995413],[-117.353928,45.996349],[-117.47993726365397,45.99756676684219],[-117.60342583450398,45.99876017344268],[-117.717852,45.999866],[-117.97765730653197,46.00016820238199],[-117.99697042960298,46.00019066717259],[-118.36779,46.000622],[-118.60678915418896,46.00086324979118],[-118.67787,46.000935],[-118.987129,45.999855],[-118.98722753956497,45.99980021352369],[-119.061462,45.958527],[-119.12612,45.932859],[-119.25715,45.939926],[-119.364396,45.921605],[-119.43213855881598,45.91320914423389],[-119.487829,45.906307],[-119.571584,45.925456],[-119.600549,45.919581],[-119.669877,45.856867],[-119.802655,45.84753],[-119.868153889391,45.838226602635686],[-119.965744,45.824365],[-119.99950515346198,45.81168492308189],[-120.07015,45.785152],[-120.141352,45.773152],[-120.210754,45.725951],[-120.282156,45.72125],[-120.40396,45.699249],[-120.48854682070397,45.69991222747849],[-120.505863,45.700048],[-120.591166,45.746547],[-120.634968,45.745847],[-120.65251676019399,45.73616973067489],[-120.68937,45.715847],[-120.855674,45.671545],[-120.895575,45.642945],[-120.91393501308399,45.64806586642348],[-120.943977,45.656445],[-121.084933,45.647893],[-121.1222,45.616067],[-121.183841,45.606441],[-121.215779,45.671238],[-121.33777,45.704949],[-121.423592,45.69399],[-121.44069582786098,45.69907379477239],[-121.52400610421999,45.72383622519919],[-121.533106,45.726541],[-121.668362,45.705082],[-121.735104,45.694039],[-121.811304,45.706761],[-121.867167,45.693277],[-121.900858,45.662009],[-121.92374936198499,45.65434950896938],[-121.951838,45.644951],[-122.00369,45.61593],[-122.101675,45.583516],[-122.183695,45.577696],[-122.24919700805198,45.54999893274119],[-122.262625,45.544321],[-122.331502,45.548241],[-122.380302,45.575941],[-122.438674,45.563585],[-122.492259,45.583281],[-122.643907,45.609739],[-122.738109,45.644138],[-122.75644390397096,45.66242102508758],[-122.774511,45.680437],[-122.76651077132999,45.728662574445195],[-122.761451,45.759163],[-122.795605,45.81],[-122.788086362595,45.851007454356086],[-122.785026,45.867699],[-122.81151,45.912725],[-122.813998,45.960984],[-122.856158,46.014469],[-122.904119,46.083734],[-122.962681,46.104817],[-123.004233,46.133823],[-123.115904,46.185268],[-123.166414,46.188973],[-123.21249359120895,46.171096458400285],[-123.280166,46.144843],[-123.36374450726598,46.14624319434849],[-123.371433,46.146372],[-123.430847,46.181827],[-123.427629,46.229348],[-123.479644,46.269131],[-123.547659,46.259109],[-123.669501,46.266832],[-123.700764,46.305278],[-123.72790381759698,46.29133558571118],[-123.75956,46.275073],[-123.806139,46.283588],[-123.875525,46.239787],[-123.909306,46.245491],[-123.954353,46.277001],[-123.969427,46.291398],[-124.080671,46.267239],[-124.064624,46.326899],[-124.057024,46.493338],[-124.069583,46.630651],[-123.960642,46.636364],[-123.923269,46.672708],[-123.975157,46.713971],[-124.080983,46.735003],[-124.09679666790497,46.794085],[-124.101232,46.810656],[-124.138225,46.905534],[-124.180111,46.926357],[-124.169113,46.994508],[-124.188544,47.157859],[-124.195893,47.174],[-124.236349,47.287287],[-124.319379,47.355559],[-124.35361567088695,47.53353708305209],[-124.355955,47.545698],[-124.412106,47.691199],[-124.471687,47.766907],[-124.539927,47.836967],[-124.61310865605198,47.88057244174858],[-124.625512,47.887963],[-124.672427,47.964414],[-124.685393,48.049238],[-124.687101,48.098657],[-124.721725,48.153185],[-124.690389,48.219745],[-124.669265,48.296353],[-124.725839,48.386012]]]]}}, {"type":"Feature","properties":{"name":"West Virginia","income":{"1995":25354,"1996":25760,"1997":27432,"1998":28460,"1999":30108,"2000":30187,"2001":31156,"2002":30695,"2003":32967,"2004":33993,"2005":33466,"2006":35028,"2007":37057,"2008":37528,"2009":37423,"2010":38241,"2011":38587,"2012":40188,"2013":41195,"2014":41030,"2015":41969}},"geometry":{"type":"Polygon","coordinates":[[[-82.598864,38.201007],[-82.58469381412559,38.24051299336969],[-82.581796,38.248592],[-82.571877,38.315781],[-82.597979,38.344909],[-82.59596426449998,38.38088976171549],[-82.593673,38.421809],[-82.560664,38.404338],[-82.50896694973129,38.414643912651684],[-82.447076,38.426982],[-82.381773,38.434783],[-82.323999,38.449268],[-82.304223,38.496308],[-82.293271,38.560283],[-82.28213334402808,38.57986079640348],[-82.27427,38.593683],[-82.218967,38.591683],[-82.175167,38.608484],[-82.185567,38.659583],[-82.201537,38.760372],[-82.20929,38.802672],[-82.16157,38.824632],[-82.134766,38.905579],[-82.09886665055427,38.96087928449329],[-82.089065,38.975978],[-82.041563,39.017878],[-82.007062,39.029578],[-81.941829,38.993295],[-81.89847,38.929603],[-81.827354,38.945898],[-81.775734,38.980737],[-81.793304,39.040353],[-81.807855,39.083978],[-81.75026684342629,39.10403119309979],[-81.742953,39.106578],[-81.75229703674009,39.18103474740589],[-81.752754,39.184676],[-81.72146813917249,39.210960809203684],[-81.711628,39.219228],[-81.678331,39.273755],[-81.613896,39.275339],[-81.565247,39.276175],[-81.559647,39.330774],[-81.503189,39.373242],[-81.456143,39.409274],[-81.412706,39.394618],[-81.393794,39.351706],[-81.37038980882629,39.348700672403396],[-81.347567,39.34577],[-81.249088,39.389992],[-81.185946,39.430731],[-81.128533,39.449375],[-81.12127385610779,39.45769741388929],[-81.07595,39.50966],[-81.03736504198706,39.538055712472584],[-80.943782,39.606926],[-80.865575,39.662751],[-80.829764,39.711839],[-80.83552169300748,39.71925180220009],[-80.869933,39.763555],[-80.824969,39.801092],[-80.824276,39.847159],[-80.82343810478588,39.85003208739639],[-80.803394,39.918762],[-80.764479,39.95025],[-80.740126,39.970793],[-80.73821843998358,40.033543226078386],[-80.736804,40.080072],[-80.705994,40.151591],[-80.70257530362257,40.157141398009685],[-80.68417321070798,40.18701797335069],[-80.644598,40.25127],[-80.606596,40.303869],[-80.631596,40.385468],[-80.62736262993687,40.395170933017184],[-80.604895,40.446667],[-80.622195,40.520497],[-80.667957,40.582496],[-80.627171,40.619936],[-80.583633,40.61552],[-80.518991,40.638801],[-80.51901711734737,40.47736314623709],[-80.51902969119408,40.39964105634069],[-80.519039,40.342101],[-80.51908437045658,40.15967199511809],[-80.51912,40.01641],[-80.51916079431449,39.96220005252189],[-80.519342,39.721403],[-80.421388,39.721189],[-80.075947,39.72135],[-80.04170201281049,39.72128703291879],[-79.91601735603777,39.72105593351879],[-79.763774,39.720776],[-79.476662,39.721078],[-79.482366,39.531689],[-79.484372,39.3443],[-79.486873,39.205961],[-79.424413,39.228171],[-79.35375,39.278039],[-79.283723,39.30964],[-79.26239211717608,39.32624382846739],[-79.166497,39.400888],[-79.091329,39.472407],[-79.06782557347339,39.47280233821589],[-79.035623,39.473344],[-78.956751,39.440264],[-78.942618,39.479614],[-78.851016,39.554044],[-78.77114,39.638387],[-78.73905,39.609697],[-78.707098,39.555857],[-78.65503617154668,39.54438224108369],[-78.590654,39.530192],[-78.46826959500288,39.526224270471694],[-78.460951,39.525987],[-78.438179,39.563524],[-78.382959,39.622246],[-78.33278802149908,39.62852759649879],[-78.313033,39.631001],[-78.225075,39.658878],[-78.08226,39.671166],[-78.02762910017326,39.620655962344095],[-78.006734,39.601337],[-77.925988,39.607642],[-77.829814,39.587288],[-77.823762,39.525907],[-77.81094389626217,39.50073916656648],[-77.798201,39.475719],[-77.740012,39.401694],[-77.74593,39.353221],[-77.719519,39.321314],[-77.778068,39.229305],[-77.809125,39.168567],[-77.828157,39.132329],[-77.82830183326728,39.132422454832486],[-78.032841,39.264403],[-78.03318346093418,39.26462369847469],[-78.03318523536657,39.26462484200518],[-78.18737,39.363989],[-78.22912953421849,39.39066388720409],[-78.347087,39.466012],[-78.337133,39.409169],[-78.34048,39.353492],[-78.401813,39.276754],[-78.40498,39.238006],[-78.428697,39.187217],[-78.413943,39.158415],[-78.508132,39.08863],[-78.53214700369618,39.05294164002129],[-78.561711,39.009007],[-78.620453,38.982601],[-78.681617,38.92584],[-78.772793,38.893742],[-78.821167,38.830982],[-78.869276,38.762991],[-78.999014,38.840074],[-79.023053,38.798613],[-79.057253,38.761413],[-79.088055,38.690115],[-79.092955,38.659517],[-79.154357,38.606518],[-79.201459,38.527821],[-79.22825588138187,38.48003955108519],[-79.23162,38.474041],[-79.297758,38.416438],[-79.31129606551438,38.41845460145499],[-79.370302,38.427244],[-79.476638,38.457228],[-79.54257,38.553217],[-79.649075,38.591515],[-79.669128,38.510883],[-79.691088,38.463744],[-79.689675,38.431439],[-79.7346,38.356728],[-79.804093,38.313922],[-79.787542,38.273298],[-79.79701353680687,38.267268121139196],[-79.850324,38.233329],[-79.916174,38.184386],[-79.938952,38.111619],[-79.96198227263537,38.06360709949329],[-79.971231,38.044326],[-80.036236,37.96792],[-80.05581159458966,37.951878220097896],[-80.131931,37.8895],[-80.199633,37.827507],[-80.218616,37.783291],[-80.258143,37.720612],[-80.290033810255,37.686136458971],[-80.292258,37.683732],[-80.22430324437678,37.62399137117089],[-80.223386,37.623185],[-80.28244,37.585481],[-80.291644,37.536505],[-80.39988,37.462314],[-80.46482,37.426144],[-80.47128294938639,37.43006549889589],[-80.544836,37.474695],[-80.664971,37.414215],[-80.770082,37.372363],[-80.836446,37.424355],[-80.85735857018977,37.421128713998996],[-80.85814811681978,37.421006906721495],[-80.865148,37.419927],[-80.883248,37.383933],[-80.835479,37.334824],[-80.919259,37.306163],[-80.98084525689279,37.30085281619049],[-80.996013,37.299545],[-81.112596,37.278497],[-81.225104,37.234874],[-81.362156,37.337687],[-81.427946,37.271015],[-81.483559,37.250604],[-81.53307,37.223414],[-81.560625,37.206663],[-81.678603,37.202467],[-81.73905503048546,37.23949710387279],[-81.744003,37.242528],[-81.774747,37.274847],[-81.849949,37.285227],[-81.896001,37.331967],[-81.933601,37.389217],[-81.93695,37.41992],[-81.984891,37.454315],[-81.932279,37.511961],[-81.968297,37.537798],[-82.064418,37.544516],[-82.141555,37.595166],[-82.226111,37.653092],[-82.296118,37.686174],[-82.32067495717779,37.74596584345939],[-82.327356,37.762233],[-82.369973,37.801749],[-82.39846481625888,37.84305415046289],[-82.41869,37.872375],[-82.487556,37.916975],[-82.47942012322297,37.938562524698085],[-82.464987,37.976859],[-82.549407,38.063063],[-82.626182,38.134835],[-82.598864,38.201007]]]}}, {"type":"Feature","properties":{"name":"Wyoming","income":{"1995":30673,"1996":31173,"1997":33197,"1998":35868,"1999":37480,"2000":38934,"2001":39988,"2002":39772,"2003":41554,"2004":43785,"2005":45501,"2006":47819,"2007":52433,"2008":54735,"2009":54400,"2010":53757,"2011":56044,"2012":55104,"2013":58424,"2014":58291,"2015":61213}},"geometry":{"type":"Polygon","coordinates":[[[-111.056888,44.866658],[-111.04431854542997,45.000880003307685],[-111.044275,45.001345],[-110.785008,45.002952],[-110.705272,44.992324],[-110.324441,44.999156],[-109.99505,45.003174],[-109.79848377243498,45.002920308285],[-109.574321,45.002631],[-109.103445,45.005904],[-109.062262,44.999623],[-108.62149349472998,44.99967637102149],[-108.500679,44.999691],[-108.24852773809597,45.00062981791279],[-107.997353,45.001565],[-107.91152278816197,45.00154400461138],[-107.351441,45.001407],[-106.888773,44.995885],[-106.26371509246498,44.99378843300149],[-106.263586,44.993788],[-106.02488002903198,44.99758412355609],[-105.848065,45.000396],[-105.07660095225397,45.000296613407386],[-105.03825218827397,45.00029167299179],[-105.025266,45.00029],[-104.057698,44.997431],[-104.05581,44.691343],[-104.05569519926098,44.57099037714218],[-104.055389,44.249983],[-104.05540637782698,44.180382874095685],[-104.05541619070499,44.14108120678338],[-104.055488,43.853477],[-104.05548799845099,43.85347599845599],[-104.055032,43.558603],[-104.05479428434798,43.503327530406],[-104.05468456842698,43.47781554171099],[-104.053876,43.289801],[-104.053127,43.000585],[-104.052586,42.630917],[-104.05266219156799,42.61176630054148],[-104.053107,42.499964],[-104.052793,42.249962],[-104.052729,42.016318],[-104.05276213709197,42.00171826586659],[-104.053026,41.885464],[-104.05282523523898,41.69795385306399],[-104.052735,41.613676],[-104.05263457163298,41.564275779573684],[-104.052287,41.393307],[-104.05228713412097,41.393214000193396],[-104.052453,41.278202],[-104.053142,41.114457],[-104.053249,41.001406],[-104.497058,41.001805],[-104.855273,40.998048],[-104.943371,40.99807410372979],[-105.276859994035,40.99817291762589],[-105.277138,40.998173],[-106.19055407870897,40.99774661257439],[-106.217573,40.997734],[-106.32116921591397,40.99821501106799],[-106.86037794866498,41.00071862923709],[-107.31779575978997,41.00284248123219],[-107.367443,41.003073],[-107.91841828984899,41.00122707064409],[-108.250649,41.000114],[-109.050076,41.000659],[-109.250735,41.001009],[-109.715409,40.998191],[-110.00071673644098,40.99742545970819],[-110.04848299568498,40.99729729285058],[-110.121639,40.997101],[-110.539819,40.996346],[-111.046723,40.997959],[-111.04663698312598,41.25162695625139],[-111.0466,41.360692],[-111.045789,41.565571],[-111.04581846484197,41.57984494822579],[-111.046689,42.001567],[-111.04708,42.34942],[-111.04553029271298,42.513912877775084],[-111.043564,42.722624],[-111.043959,42.96445],[-111.04405270511799,43.019407032899],[-111.044143,43.072364],[-111.044617,43.31572],[-111.04536056096998,43.50105145111219],[-111.04611,43.687848],[-111.046515,43.908376],[-111.04721938441998,43.983452760701795],[-111.048452,44.114831],[-111.049148,44.374925],[-111.048974,44.474072],[-111.055208,44.624927],[-111.05533272712397,44.66626230991749],[-111.055511,44.725343],[-111.056888,44.866658]]]}}, {"type":"Feature","properties":{"name":"Alabama","income":{"1995":27357,"1996":29618,"1997":30790,"1998":33204,"1999":33840,"2000":34923,"2001":34761,"2002":35943,"2003":36131,"2004":37062,"2005":36936,"2006":38811,"2007":40596,"2008":42586,"2009":40547,"2010":40538,"2011":41427,"2012":41610,"2013":42882,"2014":42917,"2015":44833}},"geometry":{"type":"Polygon","coordinates":[[[-88.46866248405128,31.893855711615586],[-88.46866,31.933173],[-88.45338776310928,32.0530492054197],[-88.43114536346278,32.22763623468889],[-88.428278,32.250143],[-88.42131222139429,32.30867912301129],[-88.38924856412427,32.578122395958594],[-88.373338,32.711825],[-88.34749024783488,32.92903478688049],[-88.34008499213928,32.991264337874995],[-88.317135,33.184123],[-88.30444281351036,33.28832],[-88.27451647078367,33.53400147778519],[-88.254445,33.698779],[-88.24838747390947,33.74490759488169],[-88.207229,34.058333],[-88.20358349521936,34.08652773146809],[-88.17326173459489,34.32103953433429],[-88.15490218400868,34.46303430043999],[-88.13955944124736,34.581696745883896],[-88.134263,34.62266],[-88.097888,34.892202],[-88.154617,34.922392],[-88.200064,34.995634],[-88.202959,35.008028],[-88.000032,35.005939],[-87.98491604369889,35.005910124325794],[-87.851886,35.005656],[-87.625025,35.003732],[-87.60609786765326,35.00351952620429],[-87.22405364187567,34.99923074197209],[-87.216683,34.999148],[-87.21075857998228,34.99904918099969],[-86.8362863159495,34.992803004216995],[-86.783648,34.991925],[-86.78362801716898,34.991924921991995],[-86.467798,34.990692],[-86.31876076546509,34.991078580442796],[-86.311274,34.991098],[-85.86394611180688,34.98703085874809],[-85.605165,34.984678],[-85.595165,34.924171],[-85.58281233378527,34.86043547447759],[-85.561424,34.750079],[-85.53440525781537,34.62379033843579],[-85.52689481816098,34.58868569273349],[-85.51304422927326,34.52394647132369],[-85.502471,34.474526],[-85.47514728110428,34.34368465787619],[-85.46314082477578,34.28619098850549],[-85.429499,34.125095],[-85.42107317522878,34.080812652607186],[-85.398871244842,33.964129286779496],[-85.398871,33.964128],[-85.38667057377278,33.90170149400329],[-85.360532,33.767957],[-85.33811629990588,33.653114391601385],[-85.314048,33.529805],[-85.30494383322488,33.4827563368455],[-85.29434686434526,33.42799314636459],[-85.23659537125276,33.12954402825069],[-85.23244140518726,33.108077093933595],[-85.232441,33.108075],[-85.18611740178916,32.87013826997159],[-85.1844,32.861317],[-85.160963,32.826672],[-85.12453322275059,32.75162960675139],[-85.11425,32.730447],[-85.088533,32.657958],[-85.07607237260477,32.60806747515709],[-85.069848,32.583146],[-85.0071,32.523868],[-85.00113083912366,32.51015478839779],[-84.99978675631009,32.5070669687837],[-84.971831,32.442843],[-84.98115029413368,32.37904007668179],[-84.983466,32.363186],[-85.008096,32.336677],[-84.955704,32.30591],[-84.891841,32.263398],[-84.91994214792587,32.230848200933295],[-84.930127,32.219051],[-84.997765,32.185445],[-85.058749,32.136018],[-85.047063,32.087389],[-85.05141112791277,32.062256083621996],[-85.06359054298467,31.991857],[-85.067829,31.967358],[-85.114031,31.89336],[-85.141831,31.839261],[-85.12915931558317,31.780278268076593],[-85.12544057734247,31.76296870341829],[-85.11893,31.732664],[-85.12553,31.694965],[-85.058169,31.620227],[-85.05796,31.57084],[-85.041881,31.544684],[-85.05168142950619,31.51954032914169],[-85.071621,31.468384],[-85.066005,31.431363],[-85.092487,31.362881],[-85.087929,31.321648],[-85.08882996353047,31.30864775549659],[-85.089774,31.295026],[-85.108192,31.258591],[-85.107516,31.186451],[-85.035615,31.108192],[-85.02110756236277,31.075463872306393],[-85.011392,31.053546],[-85.002499,31.000682],[-85.031285,31.000647],[-85.145959,31.000693],[-85.333319,30.999555],[-85.48829828893909,30.99796462328729],[-85.49800158508948,30.99786504936139],[-85.57949757633826,30.99702874841089],[-85.749715,30.995282],[-85.893632,30.993455],[-86.03503810495057,30.993749607302295],[-86.18724804898129,30.994066723462193],[-86.364974,30.994437],[-86.38864466200037,30.994528215275192],[-86.563494,30.995202],[-86.68824096424608,30.99620189000149],[-86.78569197600586,30.99698299351679],[-86.831979,30.997354],[-86.927851,30.997678],[-87.162644,30.999026],[-87.16308069276556,30.99902418387759],[-87.312206,30.998404],[-87.425791,30.998058],[-87.519533,30.997552],[-87.59882894626209,30.99742217690529],[-87.598937,30.997422],[-87.592064,30.95146],[-87.634943,30.865857],[-87.542268,30.767481],[-87.523621,30.738285],[-87.442291,30.692661],[-87.400189,30.657201],[-87.401189,30.604383],[-87.43145,30.550252],[-87.444722,30.507484],[-87.414685,30.457289],[-87.366601,30.436643],[-87.431784,30.403193],[-87.452282,30.344097],[-87.518324,30.280435],[-87.656888,30.249709],[-87.818867,30.228314],[-87.893201,30.239237],[-87.806466,30.279798],[-87.796717,30.324198],[-87.865017,30.38345],[-87.914136,30.446144],[-87.933355,30.487357],[-87.901711,30.550879],[-87.914956,30.585893],[-87.93107,30.652694],[-88.008396,30.684956],[-88.061998,30.644891],[-88.064898,30.588292],[-88.081617,30.546317],[-88.103768,30.500903],[-88.105699,30.401865],[-88.136173,30.320729],[-88.195664,30.321242],[-88.257764,30.318933],[-88.311608,30.368908],[-88.364022,30.388006],[-88.395023,30.369425],[-88.403931,30.543359],[-88.41227,30.731771],[-88.41246743135916,30.735597459215292],[-88.42602096378707,30.99828135743029],[-88.432007,31.114298],[-88.44866,31.421277],[-88.44944606901707,31.435836861277593],[-88.459478,31.621652],[-88.46362530468488,31.697942371350187],[-88.468669,31.790722],[-88.46866248405128,31.893855711615586]]]}}, {"type":"Feature","properties":{"name":"New Hampshire","income":{"1995":38017,"1996":40153,"1997":42023,"1998":45401,"1999":47284,"2000":49830,"2001":50898,"2002":51550,"2003":52409,"2004":53377,"2005":56557,"2006":59265,"2007":62048,"2008":63235,"2009":60734,"2010":60917,"2011":62436,"2012":63157,"2013":64064,"2014":66469,"2015":70003}},"geometry":{"type":"Polygon","coordinates":[[[-72.556112,42.866252],[-72.531469,42.89795],[-72.532186,42.954945],[-72.492597,42.967648],[-72.444977,43.004416],[-72.45195470906819,43.02049491063029],[-72.462248,43.044214],[-72.435191,43.086622],[-72.451802,43.153486],[-72.45039593921588,43.16121351690638],[-72.440563,43.215254],[-72.43361119795948,43.23290381226179],[-72.421583,43.263442],[-72.402532,43.32038],[-72.40690185803167,43.33744883873478],[-72.413377,43.362741],[-72.39692302503589,43.428922115998596],[-72.39689079629089,43.429051746335084],[-72.380894,43.493394],[-72.37944,43.574069],[-72.33359650135627,43.60559134158909],[-72.329522,43.608393],[-72.284805,43.72036],[-72.222069,43.759831],[-72.21150212234988,43.77301941044169],[-72.183333,43.808177],[-72.16978,43.873425],[-72.105875,43.94937],[-72.116706,43.991954],[-72.07994422400259,44.03000003018069],[-72.07969627284778,44.0302566433846],[-72.075486,44.034614],[-72.036883,44.103119],[-72.05382688361469,44.15981709380338],[-72.061338,44.184951],[-72.05399,44.246926],[-72.046302,44.291983],[-72.002314,44.324871],[-71.945163,44.337744],[-71.875863,44.33737],[-71.83779062638878,44.34776454247699],[-71.818838,44.352939],[-71.778613,44.399799],[-71.76319252131339,44.40356826277639],[-71.69092,44.421234],[-71.646551,44.468869],[-71.579974,44.501778],[-71.588076,44.54785],[-71.544922,44.579278],[-71.551722,44.627598],[-71.584574,44.665351],[-71.626909,44.747224],[-71.570402,44.805276],[-71.522393,44.880811],[-71.494403,44.911837],[-71.531605,44.976023],[-71.501088,45.013377],[-71.498399,45.069629],[-71.448678,45.109001],[-71.419058,45.170488],[-71.405636,45.198139],[-71.438546,45.239004],[-71.360664,45.269835],[-71.283684,45.301977],[-71.244499,45.268139],[-71.182587,45.241069],[-71.13943,45.242958],[-71.109349,45.282222],[-71.083924,45.305451],[-71.057861,45.000049],[-71.036705,44.736498],[-71.022992,44.500058],[-71.01946172948549,44.44036323978749],[-71.01357590381458,44.34083745255949],[-71.01127,44.301846],[-71.01027116786828,44.284888321572],[-71.008736,44.258825],[-71.001367,44.092931],[-70.989929,43.839239],[-70.98725804674599,43.79297359288418],[-70.981946,43.70096],[-70.972716,43.570255],[-70.96379267980639,43.54022095536649],[-70.954755,43.509802],[-70.96078889604699,43.47408873362158],[-70.968359,43.429283],[-70.984335,43.376128],[-70.923949,43.324768],[-70.872585,43.270152],[-70.813119,43.217252],[-70.82477671206809,43.1797631051822],[-70.824801,43.179685],[-70.8281,43.129086],[-70.819549285713,43.123230973431184],[-70.756397,43.079988],[-70.703818,43.059825],[-70.735477,43.012201],[-70.765222,42.975349],[-70.798636,42.924288],[-70.81143765483408,42.88861487845308],[-70.817296,42.87229],[-70.86475,42.870258],[-70.930799,42.884589],[-70.9665,42.868989],[-71.031201,42.859089],[-71.04871641369859,42.83106433808219],[-71.064201,42.806289],[-71.11637501217747,42.81190291443509],[-71.149703,42.815489],[-71.186104,42.790689],[-71.181803,42.73759],[-71.24538403292068,42.73655532857459],[-71.25511012181057,42.73639705328719],[-71.255605,42.736389],[-71.294205,42.69699],[-71.351874,42.698154],[-71.636214,42.704888],[-71.745817,42.707287],[-71.80538960273827,42.70891494352849],[-71.89876877193657,42.71146672080879],[-71.92903005905349,42.71229367253259],[-72.08136505018797,42.716456538541195],[-72.124526,42.717636],[-72.20361347980676,42.71981852867989],[-72.28303409251089,42.722010250623995],[-72.41203006475229,42.72557007336329],[-72.45119505182268,42.726650885493584],[-72.458519,42.726853],[-72.477615,42.761245],[-72.5396,42.804832],[-72.55390205084858,42.85803161016968],[-72.556112,42.866252]]]}}, {"type":"Feature","properties":{"name":"New Jersey","income":{"1995":44345,"1996":46872,"1997":47903,"1998":49615,"1999":51426,"2000":52990,"2001":54506,"2002":54932,"2003":56356,"2004":57338,"2005":61694,"2006":64549,"2007":67142,"2008":70347,"2009":68444,"2010":67719,"2011":67574,"2012":69705,"2013":70224,"2014":71968,"2015":72337}},"geometry":{"type":"Polygon","coordinates":[[[-75.559446,39.629812],[-75.535144,39.647212],[-75.509742,39.686113],[-75.47764,39.715013],[-75.459439,39.765813],[-75.415062,39.801919],[-75.41049247763708,39.80467223432209],[-75.3903156232519,39.81682921783048],[-75.35164821406889,39.840127153513386],[-75.341765,39.846082],[-75.293376,39.848782],[-75.25880581804768,39.85467390078439],[-75.221025,39.861113],[-75.21119606147448,39.86651863168209],[-75.183023,39.882013],[-75.14143552174727,39.89391837248129],[-75.13342,39.896213],[-75.13572,39.947112],[-75.11922,39.965412],[-75.06012997072258,39.99201100326259],[-75.059017,39.992512],[-74.989914,40.037311],[-74.97285475644559,40.046505365536284],[-74.932211,40.068411],[-74.863809,40.08221],[-74.825907,40.12391],[-74.769488,40.129145],[-74.72337929715148,40.1528955462317],[-74.721604,40.15381],[-74.74849765725779,40.18490861410399],[-74.760605,40.198909],[-74.823907,40.241508],[-74.856508,40.277407],[-74.90331,40.315607],[-74.92811056909137,40.33982844768929],[-74.946006,40.357306],[-74.969597,40.39977],[-75.024775,40.403455],[-75.056102,40.416066],[-75.070568,40.455165],[-75.062227,40.481391],[-75.078503,40.548296],[-75.136748,40.575731],[-75.186737,40.569406],[-75.18819987812519,40.59261336664859],[-75.18923640135588,40.609056961122086],[-75.191059,40.637971],[-75.19184187174827,40.677242125441396],[-75.192612,40.715874],[-75.177477,40.764225],[-75.11135873167228,40.789982289214386],[-75.108505,40.791094],[-75.090962,40.849187],[-75.065438,40.885682],[-75.09772,40.926679],[-75.12325394420847,40.96530553438769],[-75.133086,40.980179],[-75.070532,41.01862],[-75.015271,41.061215],[-74.99238599518219,41.09302824699339],[-74.98304207424778,41.106017558856784],[-74.979873,41.110423],[-74.905256,41.155668],[-74.867405,41.22777],[-74.815703,41.296151],[-74.760325,41.340325],[-74.694914,41.357423],[-74.457584,41.248225],[-74.36703826144738,41.20421147244379],[-74.301994,41.172594],[-74.234473,41.142883],[-74.23436283123036,41.142835271534594],[-74.21161764319858,41.132981363536295],[-74.041054,41.059088],[-73.89398186003588,40.997198203538886],[-73.893979,40.997197],[-73.90728,40.951498],[-73.92047152937927,40.918606332041],[-73.92203089786648,40.914718213458784],[-73.93489258096068,40.88264898194209],[-73.938081,40.874699],[-73.94748456908319,40.85777345328739],[-73.96583451704629,40.82474525955859],[-73.968082,40.8207],[-73.97120801828238,40.81631562632088],[-73.98459249468017,40.79754332855229],[-74.013784,40.756601],[-74.02349153373218,40.73745316548729],[-74.02947453619967,40.72565186308668],[-74.03092708568377,40.72278675049359],[-74.04115624430348,40.70261002570879],[-74.046966591833,40.69114928026859],[-74.047313,40.690466],[-74.06772033031899,40.67038059424459],[-74.07094353771528,40.66720823277558],[-74.086806,40.651596],[-74.16014678315318,40.64607651644479],[-74.170611,40.645289],[-74.20012290199108,40.63186890194569],[-74.202247,40.630903],[-74.203688,40.592691],[-74.216839,40.558618],[-74.249211,40.545064],[-74.260611,40.502436],[-74.261889,40.464706],[-74.22465246601467,40.448662489486495],[-74.206188,40.440707],[-74.157094,40.447571],[-74.108295,40.443788],[-74.047884,40.418908],[-74.019334,40.471244],[-73.997943,40.476668],[-73.976982,40.408508],[-73.971381,40.34801],[-73.981681,40.279411],[-74.00102079443458,40.216966591977894],[-74.030181,40.122814],[-74.03496238226347,40.102584305948184],[-74.064135,39.979157],[-74.077247,39.910991],[-74.090945,39.799978],[-74.09961891432518,39.763784361495794],[-74.101443,39.756173],[-74.190974,39.625118],[-74.29101533615479,39.508369797497785],[-74.291585,39.507705],[-74.304343,39.471445],[-74.36699,39.402017],[-74.412692,39.360816],[-74.521797,39.313816],[-74.54078785558248,39.30002549118439],[-74.581008,39.270819],[-74.646595,39.212002],[-74.67143,39.179802],[-74.714341,39.119804],[-74.705876,39.102937],[-74.778777,39.023073],[-74.807917,38.985948],[-74.864458,38.94041],[-74.933571,38.928519],[-74.967274,38.933413],[-74.955363,39.001262],[-74.903664,39.087437],[-74.885914,39.143627],[-74.905181,39.174945],[-74.91515580556269,39.17669750351878],[-74.998002,39.191253],[-75.048487,39.215222],[-75.090794,39.210802],[-75.136667,39.181883],[-75.166667,39.222577],[-75.21251,39.262755],[-75.244357,39.2857],[-75.285333,39.292212],[-75.326754,39.332473],[-75.355558,39.347823],[-75.399304,39.37949],[-75.41710707748808,39.388910686713686],[-75.442393,39.402291],[-75.465212,39.43893],[-75.536431,39.460559],[-75.528088,39.498114],[-75.527676,39.535278],[-75.512732,39.578],[-75.543965,39.596],[-75.559446,39.629812]]]}}, {"type":"Feature","properties":{"name":"North Dakota","income":{"1995":29321,"1996":30798,"1997":31764,"1998":32430,"1999":34206,"2000":35636,"2001":36177,"2002":36223,"2003":38223,"2004":39233,"2005":40818,"2006":41852,"2007":43936,"2008":45996,"2009":47898,"2010":48878,"2011":52135,"2012":54579,"2013":56800,"2014":60227,"2015":61674}},"geometry":{"type":"Polygon","coordinates":[[[-104.048736,48.999877],[-103.375467,48.998951],[-102.93877701942799,48.99935025028508],[-102.850455,48.999431],[-102.216993,48.998553],[-102.02114942465897,48.99875660541088],[-101.625438,48.999168],[-101.496737,48.99914483400529],[-101.125434,48.999078],[-100.431676,48.999398],[-100.182706982328,48.99923022464128],[-99.91378,48.999049],[-99.52570005907168,48.999271291155495],[-99.376068,48.999357],[-98.999803372711,48.999986295652384],[-98.869037,49.000205],[-97.95020501151556,49.00051511893839],[-97.77575,49.000574],[-97.229039,49.000687],[-97.227854,48.945864],[-97.187362,48.867598],[-97.152588,48.772602],[-97.121253,48.713593],[-97.100009,48.667926],[-97.142915,48.583733],[-97.14772356830088,48.54389168365058],[-97.14810346613356,48.54074404618669],[-97.149122,48.532305],[-97.139173,48.430528],[-97.137904,48.344585],[-97.129533,48.257815],[-97.14191038719827,48.19362761887449],[-97.14584495947489,48.17322348299049],[-97.146745,48.168556],[-97.105616,48.091362],[-97.068987,48.026267],[-97.037354,47.933279],[-96.996364,47.844398],[-96.928506,47.744884],[-96.89349330133977,47.672126959443695],[-96.882376,47.649025],[-96.854073,47.57201],[-96.85595934905318,47.49917322952899],[-96.85748,47.440457],[-96.84022,47.276981],[-96.83600959454186,47.237981875487094],[-96.82656912722827,47.150539],[-96.819078,47.081152],[-96.833504,47.01011],[-96.763973,46.912507],[-96.788803,46.777575],[-96.786845,46.692805],[-96.790523,46.63688],[-96.78978651304978,46.63574667271669],[-96.78578618259849,46.629590849260886],[-96.744436,46.56596],[-96.709095,46.435294],[-96.647296,46.358499],[-96.60104,46.319554],[-96.59567,46.21985],[-96.554507,46.083978],[-96.57269749419397,46.02189167135768],[-96.574264,46.016545],[-96.563672,45.935245],[-97.082093,45.935842],[-97.228291,45.93565659564609],[-97.542598,45.935258],[-97.77704,45.935393],[-97.97877780962337,45.93593399209868],[-98.00810179827778,45.936012629049294],[-98.070515,45.93618],[-98.414518,45.936504],[-98.625379,45.938228],[-98.72437441388807,45.93867473326149],[-99.005642,45.939944],[-99.00575435015247,45.93994430912839],[-99.092868,45.940184],[-99.34496,45.940299],[-99.490254,45.940362],[-99.61116,45.941098],[-99.71807104288217,45.94090700349639],[-99.718073,45.940907],[-99.88006209480658,45.94167091580218],[-99.880292,45.941672],[-100.152084,45.942486],[-100.294126,45.943269],[-100.49935421538399,45.94363199881429],[-100.511793,45.943654],[-100.511949026151,45.943654070434484],[-100.76211,45.943767],[-101.106826,45.943984],[-101.365283,45.944092],[-101.557276,45.9441],[-101.794606,45.944397],[-101.99861707823398,45.94453697735689],[-102.00067992101798,45.944538392727495],[-102.087555,45.944598],[-102.32823,45.944806],[-102.550947,45.945015],[-102.704871,45.945072],[-102.880252,45.945069],[-102.94206996119098,45.94509441135319],[-102.99566801913798,45.94511644377148],[-103.218396,45.945208],[-103.434851,45.945291],[-103.660779,45.945241],[-104.045443,45.94531],[-104.04546595892799,46.28018804821068],[-104.045469,46.324545],[-104.045045,46.509788],[-104.04512541332298,46.540929928548984],[-104.045385103689,46.641501059121794],[-104.045572,46.713881],[-104.045542,46.933887],[-104.044788,47.12743],[-104.04530830986899,47.330127858805994],[-104.045313,47.331955],[-104.04497671640497,47.397069201282385],[-104.043912,47.603229],[-104.042384,47.803256],[-104.043933,47.971515],[-104.04409321534798,47.99609835556468],[-104.04409327282099,47.99610717418708],[-104.045692,48.241415],[-104.04678216170598,48.38930073114548],[-104.047555,48.49414],[-104.04808756883199,48.63401237339858],[-104.0489,48.847387],[-104.048736,48.999877]]]}}, {"type":"Feature","properties":{"name":"Pennsylvania","income":{"1995":34437,"1996":35109,"1997":37267,"1998":39116,"1999":38918,"2000":41419,"2001":42288,"2002":42043,"2003":42952,"2004":43714,"2005":44545,"2006":46256,"2007":48562,"2008":50702,"2009":49501,"2010":49245,"2011":50221,"2012":51225,"2013":52005,"2014":53224,"2015":55683}},"geometry":{"type":"Polygon","coordinates":[[[-80.519891,40.906661],[-80.51964377254728,40.987392654005795],[-80.51922208608089,41.12509356679578],[-80.51919669032499,41.133386502548895],[-80.518893,41.232556],[-80.51900013136428,41.33350214419358],[-80.51916516989557,41.48901219015458],[-80.51917675035338,41.499924051205994],[-80.519357,41.669767],[-80.51939672669049,41.84956299055929],[-80.519425,41.977523],[-80.329976,42.036168],[-80.154084,42.114757],[-80.136213,42.149937],[-80.088512,42.173184],[-80.02116492565449,42.163240309016],[-80.020323,42.163116],[-79.923924,42.207546],[-79.844661,42.235486],[-79.761951,42.26986],[-79.762122,42.131246],[-79.761313,41.998808],[-79.61083577498667,41.99851990410838],[-79.472472,41.998255],[-79.06126440315988,41.998838109911],[-78.983065,41.998949],[-78.91885736361519,41.99910319868938],[-78.59665,41.999877],[-78.30812896044657,41.99907113474139],[-78.271204,41.998968],[-78.20660303785819,41.99908830575759],[-78.031177,41.999415],[-77.83203,41.998524],[-77.74993092512727,41.99875544032899],[-77.61002011447597,41.99914985407959],[-77.007635,42.000848],[-76.96572875942668,42.00078339504688],[-76.92684636295428,42.00072345181729],[-76.558118,42.000155],[-76.55762414356937,42.000148716341684],[-76.47303088580799,41.999072381007],[-76.462155,41.998934],[-76.14551899478208,41.998866463308],[-76.10584,41.998858],[-75.870677,41.998828],[-75.55311253909508,41.999295228473486],[-75.48314927095889,41.999398164522695],[-75.477144,41.999407],[-75.35985992915047,41.993685888904594],[-75.341125,41.992772],[-75.291762,41.947092],[-75.263005,41.885109],[-75.190203,41.862454],[-75.14666489928587,41.85012593014629],[-75.113369,41.840698],[-75.074412,41.802191],[-75.053431,41.752538],[-75.049281,41.641862],[-75.04619860591167,41.60376401990269],[-75.043879,41.575094],[-74.982463,41.496467],[-74.890358,41.455324],[-74.799546,41.43129],[-74.75627183472518,41.42762742854339],[-74.734893,41.425818],[-74.694914,41.357423],[-74.760325,41.340325],[-74.815703,41.296151],[-74.867405,41.22777],[-74.905256,41.155668],[-74.979873,41.110423],[-74.98304207424778,41.106017558856784],[-74.99238599518219,41.09302824699339],[-75.015271,41.061215],[-75.070532,41.01862],[-75.133086,40.980179],[-75.12325394420847,40.96530553438769],[-75.09772,40.926679],[-75.065438,40.885682],[-75.090962,40.849187],[-75.108505,40.791094],[-75.11135873167228,40.789982289214386],[-75.177477,40.764225],[-75.192612,40.715874],[-75.19184187174827,40.677242125441396],[-75.191059,40.637971],[-75.18923640135588,40.609056961122086],[-75.18819987812519,40.59261336664859],[-75.186737,40.569406],[-75.136748,40.575731],[-75.078503,40.548296],[-75.062227,40.481391],[-75.070568,40.455165],[-75.056102,40.416066],[-75.024775,40.403455],[-74.969597,40.39977],[-74.946006,40.357306],[-74.92811056909137,40.33982844768929],[-74.90331,40.315607],[-74.856508,40.277407],[-74.823907,40.241508],[-74.760605,40.198909],[-74.74849765725779,40.18490861410399],[-74.721604,40.15381],[-74.72337929715148,40.1528955462317],[-74.769488,40.129145],[-74.825907,40.12391],[-74.863809,40.08221],[-74.932211,40.068411],[-74.97285475644559,40.046505365536284],[-74.989914,40.037311],[-75.059017,39.992512],[-75.06012997072258,39.99201100326259],[-75.11922,39.965412],[-75.13572,39.947112],[-75.13342,39.896213],[-75.14143552174727,39.89391837248129],[-75.183023,39.882013],[-75.21119606147448,39.86651863168209],[-75.221025,39.861113],[-75.25880581804768,39.85467390078439],[-75.293376,39.848782],[-75.341765,39.846082],[-75.35164821406889,39.840127153513386],[-75.3903156232519,39.81682921783048],[-75.41049247763708,39.80467223432209],[-75.415062,39.801919],[-75.481207,39.829191],[-75.570433,39.839185],[-75.59431690522008,39.834594973091285],[-75.662846,39.821425],[-75.717059,39.792325],[-75.753228,39.757989],[-75.773786,39.7222],[-75.788596,39.722199],[-75.81207998484679,39.72216980924989],[-76.13569742699018,39.721767550606685],[-76.23327934711658,39.72164625562789],[-76.233485,39.721646],[-76.23968374111459,39.72164198992459],[-76.41898,39.721526],[-76.56947511721158,39.72145855910529],[-76.715771,39.721393],[-76.78709719975758,39.72104814611128],[-76.991062,39.720062],[-76.99931802633319,39.72006767235259],[-77.21702375523738,39.72021724838539],[-77.23995,39.720233],[-77.45943341952388,39.72022917164499],[-77.46914500368037,39.720229002249994],[-77.469274,39.720229],[-77.768644,39.721538],[-78.075861,39.722448],[-78.09897069616667,39.72246619442808],[-78.342593,39.722658],[-78.34283351857438,39.72265829292649],[-78.38047706456398,39.72270413883999],[-78.723578,39.723122],[-78.80829952962156,39.72307095627689],[-78.93117513430978,39.72299692517329],[-79.045576,39.722928],[-79.39245840502238,39.72143935864009],[-79.476662,39.721078],[-79.763774,39.720776],[-79.91601735603777,39.72105593351879],[-80.04170201281049,39.72128703291879],[-80.075947,39.72135],[-80.421388,39.721189],[-80.519342,39.721403],[-80.51916079431449,39.96220005252189],[-80.51912,40.01641],[-80.51908437045658,40.15967199511809],[-80.519039,40.342101],[-80.51902969119408,40.39964105634069],[-80.51901711734737,40.47736314623709],[-80.518991,40.638801],[-80.51970511259918,40.851336778685386],[-80.51986970768618,40.900323934248895],[-80.51987684674039,40.90244867541969],[-80.519891,40.906661]]]}}, {"type":"Feature","properties":{"name":"Vermont","income":{"1995":32350,"1996":33352,"1997":35210,"1998":37947,"1999":39571,"2000":40537,"2001":41342,"2002":41962,"2003":42649,"2004":44548,"2005":45695,"2006":47778,"2007":49698,"2008":52111,"2009":51219,"2010":49393,"2011":52033,"2012":52700,"2013":52511,"2014":54153,"2015":56883}},"geometry":{"type":"Polygon","coordinates":[[[-73.416319,44.099422],[-73.39986856936459,44.152485647691684],[-73.395399,44.166903],[-73.349889,44.230356],[-73.316618,44.257769],[-73.31745597466508,44.26352218987678],[-73.324229,44.310023],[-73.334637,44.356877],[-73.320954,44.382669],[-73.293613,44.440559],[-73.312871,44.507246],[-73.34798323242649,44.54616285359699],[-73.36268281274378,44.56245522168669],[-73.367275,44.567545],[-73.389966,44.61962],[-73.36556,44.700297],[-73.357671,44.751018],[-73.33443,44.802188],[-73.34201248394999,44.80807553866099],[-73.365678,44.826451],[-73.379822,44.857037],[-73.338979,44.917681],[-73.34474,44.970468],[-73.343124,45.01084],[-73.19231044906688,45.01286116295209],[-73.16992381668568,45.013161182623485],[-73.048386,45.01479],[-72.93644,45.014267],[-72.582371,45.011543],[-72.55427161622349,45.0094677206535],[-72.532503,45.00786],[-72.348583,45.005625],[-72.023292,45.006792],[-71.915009,45.007791],[-71.89771151185879,45.00807227383668],[-71.691898,45.011419],[-71.60984,45.012709],[-71.501088,45.013377],[-71.531605,44.976023],[-71.494403,44.911837],[-71.522393,44.880811],[-71.570402,44.805276],[-71.626909,44.747224],[-71.584574,44.665351],[-71.551722,44.627598],[-71.544922,44.579278],[-71.588076,44.54785],[-71.579974,44.501778],[-71.646551,44.468869],[-71.69092,44.421234],[-71.76319252131339,44.40356826277639],[-71.778613,44.399799],[-71.818838,44.352939],[-71.83779062638878,44.34776454247699],[-71.875863,44.33737],[-71.945163,44.337744],[-72.002314,44.324871],[-72.046302,44.291983],[-72.05399,44.246926],[-72.061338,44.184951],[-72.05382688361469,44.15981709380338],[-72.036883,44.103119],[-72.075486,44.034614],[-72.07969627284778,44.0302566433846],[-72.07994422400259,44.03000003018069],[-72.116706,43.991954],[-72.105875,43.94937],[-72.16978,43.873425],[-72.183333,43.808177],[-72.21150212234988,43.77301941044169],[-72.222069,43.759831],[-72.284805,43.72036],[-72.329522,43.608393],[-72.33359650135627,43.60559134158909],[-72.37944,43.574069],[-72.380894,43.493394],[-72.39689079629089,43.429051746335084],[-72.39692302503589,43.428922115998596],[-72.413377,43.362741],[-72.40690185803167,43.33744883873478],[-72.402532,43.32038],[-72.421583,43.263442],[-72.43361119795948,43.23290381226179],[-72.440563,43.215254],[-72.45039593921588,43.16121351690638],[-72.451802,43.153486],[-72.435191,43.086622],[-72.462248,43.044214],[-72.45195470906819,43.02049491063029],[-72.444977,43.004416],[-72.492597,42.967648],[-72.532186,42.954945],[-72.531469,42.89795],[-72.556112,42.866252],[-72.55390205084858,42.85803161016968],[-72.5396,42.804832],[-72.477615,42.761245],[-72.458519,42.726853],[-72.51671118278219,42.728467669829186],[-72.809113,42.736581],[-72.86429185484538,42.737713885159195],[-72.93026261251798,42.73906834045759],[-73.01864861335038,42.740883006399784],[-73.02301789329009,42.74097271272689],[-73.14249512051438,42.743425717196885],[-73.264957,42.74594],[-73.290944,42.80192],[-73.278673,42.83341],[-73.273832807021,42.94363174752649],[-73.27000873116357,43.030714292687485],[-73.26978,43.035923],[-73.25535583805758,43.314712398599994],[-73.252832,43.363493],[-73.242042,43.534925],[-73.292113,43.584509],[-73.327702,43.625913],[-73.395767,43.568087],[-73.424977,43.598775],[-73.414546,43.658209],[-73.393723,43.6992],[-73.36110715168428,43.75323345728389],[-73.350707,43.770463],[-73.38252614953988,43.80815898854949],[-73.390302,43.817371],[-73.374051,43.875563],[-73.407742,43.929887],[-73.411248,43.975596],[-73.405977,44.011485],[-73.43688,44.042578],[-73.416319,44.099422]]]}} ] } ================================================ FILE: examples/.eslintrc ================================================ { "rules": { "import/no-unresolved": 0, "import/no-extraneous-dependencies": 0 } } ================================================ FILE: examples/get-started/basic/README.md ================================================ # react-map-gl Example: Using Map as a stateful component This example shows a minimal app configuration to use react-map-gl's Map component with automatic view state updates. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `app.js`, or set a `MapboxAccessToken` environment variable in the command line. Alternative to acquiring a Mapbox token, visit the [maplibre-gl example](../maplibre). ```bash npm i npm run start ``` To build a production version: ```bash npm run build ``` ================================================ FILE: examples/get-started/basic/app.jsx ================================================ /* global document */ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Marker} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; const MAPBOX_TOKEN = ''; // Set your mapbox token here function Root() { return ( ); } const root = createRoot(document.body.appendChild(document.createElement('div'))); root.render(); ================================================ FILE: examples/get-started/basic/index.html ================================================ react-map-gl Example ================================================ FILE: examples/get-started/basic/package.json ================================================ { "scripts": { "start": "vite --open", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/get-started/basic/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/get-started/controlled/README.md ================================================ # react-map-gl Example: Using Map as a controlled component This example shows a minimal app configuration to use react-map-gl's Map component with external view state management. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `app.js`, or set a `MapboxAccessToken` environment variable in the command line. Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. ```bash npm i npm run start ``` To build a production version: ```bash npm run build ``` ================================================ FILE: examples/get-started/controlled/app.jsx ================================================ /* global document */ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Marker} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; const MAPBOX_TOKEN = ''; // Set your mapbox token here function Root() { const [viewState, setViewState] = React.useState({ latitude: 37.8, longitude: -122.4, zoom: 14 }); return ( setViewState(evt.viewState)} style={{width: 800, height: 600}} mapStyle="mapbox://styles/mapbox/streets-v9" mapboxAccessToken={MAPBOX_TOKEN} > ); } const root = createRoot(document.body.appendChild(document.createElement('div'))); root.render(); ================================================ FILE: examples/get-started/controlled/index.html ================================================ react-map-gl Example ================================================ FILE: examples/get-started/controlled/package.json ================================================ { "scripts": { "start": "vite --open", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/get-started/controlled/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/get-started/hook/README.md ================================================ # react-map-gl Example: Using Map with a State Management System This example shows how to use react-map-gl's Map component with the `useMap` hook. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `map.js`, or set a `MapboxAccessToken` environment variable in the command line. Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. ```bash npm i npm run start ``` To build a production version: ```bash npm run build ``` ================================================ FILE: examples/get-started/hook/app.jsx ================================================ /* global document */ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {MapProvider} from 'react-map-gl/mapbox'; import Map from './map'; import Controls from './controls'; function Root() { // Note: `useMap` will not work here, only child components of `MapProvider` or `Map` can use `useMap` return ( ); } const root = createRoot(document.body.appendChild(document.createElement('div'))); root.render(); ================================================ FILE: examples/get-started/hook/controls.jsx ================================================ import * as React from 'react'; import {useCallback, useState, useEffect} from 'react'; import {useMap} from 'react-map-gl/mapbox'; export default function Controls() { /** * ## This is how `useMap` works: * ``` * const maps = useMap(); * console.log('Controls useMap()', maps); * ``` * ### First render: * ``` * { * "current": undefined * } * ``` * ### Second render: * ``` * { * "current": undefined, * "mymap": {...} // See https://visgl.github.io/react-map-gl/docs/api-reference/types#mapref * } * ``` */ const {mymap} = useMap(); // `mymap` is the id in const [inputValue, setInputValue] = useState(''); const [hasError, setError] = useState(false); useEffect(() => { if (!mymap) return undefined; const onMove = () => { const {lng, lat} = mymap.getCenter(); setInputValue(`${lng.toFixed(3)}, ${lat.toFixed(3)}`); setError(false); }; mymap.on('move', onMove); onMove(); return () => { mymap.off('move', onMove); }; }, [mymap]); const onChange = useCallback(evt => { setInputValue(evt.target.value); }, []); const onSubmit = useCallback(() => { if (!mymap) return; const [lng, lat] = inputValue.split(',').map(Number); if (Math.abs(lng) <= 180 && Math.abs(lat) <= 85) { mymap.easeTo({ center: [lng, lat], duration: 1000 }); } else { setError(true); } }, [mymap, inputValue]); return (
MAP CENTER:
); } ================================================ FILE: examples/get-started/hook/controls2.jsx ================================================ // import {useMap} from 'react-map-gl/mapbox'; export default function Controls2() { /** * ## This is how `useMap` works: * This component does nothing. It's purpose is to demo `useMap`. * When a component is a child of ``, `useMap` has a `current` field that references the containing map. * See https://visgl.github.io/react-map-gl/docs/api-reference/use-map * See https://visgl.github.io/react-map-gl/docs/api-reference/types#mapref * ``` * const maps = useMap(); * console.log('Controls2 useMap()', maps); * ``` * ### First render: * ``` * { * "current": {...}, // this is the same as `mymap` * "mymap": {...} * } * ``` */ return null; } ================================================ FILE: examples/get-started/hook/index.html ================================================ react-map-gl Example ================================================ FILE: examples/get-started/hook/map.jsx ================================================ import * as React from 'react'; import Map from 'react-map-gl/mapbox'; // import {useMap} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; import Controls2 from './controls2'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function MapView() { /** * ## This is how `useMap` works: * ``` * const maps = useMap(); * console.log('MapView useMap()', maps); * ``` * ### First render: * ``` * { * "current": undefined * } * Second render: * { * "current": undefined, * "mymap": {...} // See https://visgl.github.io/react-map-gl/docs/api-reference/types#mapref * } * ``` */ return ( ); } ================================================ FILE: examples/get-started/hook/package.json ================================================ { "scripts": { "start": "vite --open", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/get-started/hook/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/get-started/maplibre/README.md ================================================ # react-map-gl Example: Using with Maplibre This example shows a minimal app configuration to use react-map-gl with [Maplibre GL JS](https://maplibre.org/). ## Usage ```bash npm i npm run start ``` To build a production version: ```bash npm run build ``` ## Attribution The basemap in this example is provided by [CARTO free basemap service](https://carto.com/basemaps). ================================================ FILE: examples/get-started/maplibre/app.jsx ================================================ /* global document */ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Marker} from 'react-map-gl/maplibre'; import 'maplibre-gl/dist/maplibre-gl.css'; function Root() { return ( ); } const root = createRoot(document.body.appendChild(document.createElement('div'))); root.render(); ================================================ FILE: examples/get-started/maplibre/index.html ================================================ react-map-gl Example ================================================ FILE: examples/get-started/maplibre/package.json ================================================ { "scripts": { "start": "vite --open", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/get-started/nextjs/.gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.js # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* # local env files .env.local .env.development.local .env.test.local .env.production.local # vercel .vercel ================================================ FILE: examples/get-started/nextjs/README.md ================================================ # react-map-gl Example: Using Map with Server Side Rendering This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `pages/index.js`, or set a `MapboxAccessToken` environment variable in the command line. Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. ## Getting Started First, run the development server: ```bash npm run dev # or yarn dev ``` Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. ## Learn More To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. ================================================ FILE: examples/get-started/nextjs/next.config.js ================================================ const webpack = require('webpack'); module.exports = { reactStrictMode: true, webpack: config => { // Optional: Enables reading mapbox token from environment variable config.plugins.push(new webpack.EnvironmentPlugin({MapboxAccessToken: ''})); return config; } }; ================================================ FILE: examples/get-started/nextjs/package.json ================================================ { "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "next": "12.0.7", "react": "17.0.2", "react-dom": "17.0.2", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "eslint": "8.5.0", "eslint-config-next": "12.0.7" } } ================================================ FILE: examples/get-started/nextjs/pages/_app.js ================================================ import * as React from 'react'; export default function MyApp({Component, pageProps}) { return ; } ================================================ FILE: examples/get-started/nextjs/pages/index.js ================================================ import * as React from 'react'; import Head from 'next/head'; import Map, {Marker} from 'react-map-gl/mapbox'; import 'mapbox-gl/dist/mapbox-gl.css'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function Home() { return (
react-map-gl example
); } ================================================ FILE: examples/get-started/redux/README.md ================================================ # react-map-gl Example: Using Map with a State Management System This example shows how to use react-map-gl's Map component with react-redux. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `map.js`, or set a `MapboxAccessToken` environment variable in the command line. Alternative to acquiring a Mapbox token, you can install `maplibre-gl` and change all `import from 'react-map-gl/mapbox'` to `import from 'react-map-gl/maplibre'`. You also need to supply a third-party or self-hosted `mapStyle` URL. ```bash npm i npm run start ``` To build a production version: ```bash npm run build ``` ================================================ FILE: examples/get-started/redux/app.jsx ================================================ /* global document */ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Provider} from 'react-redux'; import store from './store'; import Map from './map'; import Controls from './controls'; function Root() { return ( ); } const root = createRoot(document.body.appendChild(document.createElement('div'))); root.render(); ================================================ FILE: examples/get-started/redux/controls.jsx ================================================ import * as React from 'react'; import {useCallback, useState, useEffect} from 'react'; import {useSelector, useDispatch} from 'react-redux'; export default function Controls() { const viewState = useSelector(s => s.viewState); const dispatch = useDispatch(); const [inputValue, setInputValue] = useState(''); const [hasError, setError] = useState(false); useEffect(() => { setInputValue(`${viewState.longitude.toFixed(3)}, ${viewState.latitude.toFixed(3)}`); setError(false); }, [viewState]); const onChange = useCallback(evt => { setInputValue(evt.target.value); }, []); const onSubmit = useCallback(() => { const [lng, lat] = inputValue.split(',').map(Number); if (Math.abs(lng) <= 180 && Math.abs(lat) <= 85) { dispatch({ type: 'setViewState', payload: {...viewState, longitude: lng, latitude: lat} }); setError(false); } else { setError(true); } }, [inputValue]); return (
MAP CENTER:
); } ================================================ FILE: examples/get-started/redux/index.html ================================================ react-map-gl Example ================================================ FILE: examples/get-started/redux/map.jsx ================================================ import * as React from 'react'; import Map from 'react-map-gl/mapbox'; import {useCallback} from 'react'; import {useSelector, useDispatch} from 'react-redux'; import 'mapbox-gl/dist/mapbox-gl.css'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function MapView() { const mapStyle = useSelector(s => s.mapStyle); const viewState = useSelector(s => s.viewState); const dispatch = useDispatch(); const onMove = useCallback(evt => { dispatch({type: 'setViewState', payload: evt.viewState}); }, []); return ( ); } ================================================ FILE: examples/get-started/redux/package.json ================================================ { "scripts": { "start": "vite --open", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "react-redux": "^7.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/get-started/redux/store.js ================================================ import {createStore} from 'redux'; function mapStateReducer(state, action) { switch (action.type) { case 'setViewState': return {...state, viewState: action.payload}; default: return state; } } const defaultMapState = { mapStyle: 'mapbox://styles/mapbox/streets-v11', viewState: { latitude: 37.8, longitude: -122.4, zoom: 14 } }; export default createStore(mapStateReducer, defaultMapState); ================================================ FILE: examples/get-started/redux/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/clusters/README.md ================================================ # Example: Supercluster This app reproduces Mapbox's [Create and style clusters](https://docs.mapbox.com/mapbox-gl-js/example/cluster/) example. This example showcases how to visualize points as clusters. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/clusters/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/clusters/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/clusters/src/app.tsx ================================================ import * as React from 'react'; import {useRef} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import {clusterLayer, clusterCountLayer, unclusteredPointLayer} from './layers'; import type {MapRef} from 'react-map-gl/mapbox'; import type {GeoJSONSource} from 'mapbox-gl'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { const mapRef = useRef(null); const onClick = event => { const feature = event.features[0]; const clusterId = feature.properties.cluster_id; const mapboxSource = mapRef.current.getSource('earthquakes') as GeoJSONSource; mapboxSource.getClusterExpansionZoom(clusterId, (err, zoom) => { if (err) { return; } mapRef.current.easeTo({ center: feature.geometry.coordinates, zoom, duration: 500 }); }); }; return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/clusters/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Create and Style Clusters

Use Mapbox GL JS' built-in functions to visualize points as clusters.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/clusters/src/layers.ts ================================================ import type {LayerProps} from 'react-map-gl/mapbox'; export const clusterLayer: LayerProps = { id: 'clusters', type: 'circle', source: 'earthquakes', filter: ['has', 'point_count'], paint: { 'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'], 'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40] } }; export const clusterCountLayer: LayerProps = { id: 'cluster-count', type: 'symbol', source: 'earthquakes', filter: ['has', 'point_count'], layout: { 'text-field': '{point_count_abbreviated}', 'text-font': ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'], 'text-size': 12 } }; export const unclusteredPointLayer: LayerProps = { id: 'unclustered-point', type: 'circle', source: 'earthquakes', filter: ['!', ['has', 'point_count']], paint: { 'circle-color': '#11b4da', 'circle-radius': 4, 'circle-stroke-width': 1, 'circle-stroke-color': '#fff' } }; ================================================ FILE: examples/mapbox/clusters/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/clusters/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/controls/README.md ================================================ # Example: Controls Demonstrates how various control components can be used with react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/controls/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/controls/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/controls/src/app.tsx ================================================ import * as React from 'react'; import {useState, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import Map, { Marker, Popup, NavigationControl, FullscreenControl, ScaleControl, GeolocateControl } from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import Pin from './pin'; import CITIES from '../../../.data/cities.json'; const TOKEN = ''; // Set your mapbox token here export default function App() { const [popupInfo, setPopupInfo] = useState(null); const pins = useMemo( () => CITIES.map((city, index) => ( { // If we let the click event propagates to the map, it will immediately close the popup // with `closeOnClick: true` e.originalEvent.stopPropagation(); setPopupInfo(city); }} > )), [] ); return ( <> {pins} {popupInfo && ( setPopupInfo(null)} >
{popupInfo.city}, {popupInfo.state} |{' '} Wikipedia
)}
); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/controls/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Marker, Popup, NavigationControl and FullscreenControl

Map showing top 20 most populated cities of the United States. Click on a marker to learn more.

Data source:{' '} Wikipedia

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/controls/src/pin.tsx ================================================ import * as React from 'react'; const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 C20.1,15.8,20.2,15.8,20.2,15.7z`; const pinStyle = { cursor: 'pointer', fill: '#d00', stroke: 'none' }; function Pin({size = 20}) { return ( ); } export default React.memo(Pin); ================================================ FILE: examples/mapbox/controls/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/controls/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/custom-cursor/README.md ================================================ # Example: Custom Cursor This example showcases how to dynamically change the cursor over the map based on interactivity. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/custom-cursor/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/custom-cursor/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/custom-cursor/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map, {MapStyle} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import MAP_STYLE from '../../map-style-basic-v8.json'; const MAPBOX_TOKEN = ''; // Set your mapbox token here const initialViewState = { longitude: -122.48, latitude: 37.78, zoom: 15.5, bearing: 0, pitch: 0 }; export default function App() { const [cursor, setCursor] = useState('auto'); const [interactiveLayerIds, setInteractiveLayerIds] = useState(['nonexist']); const onInteractiveLayersChange = useCallback(layerFilter => { setInteractiveLayerIds(MAP_STYLE.layers.map(layer => layer.id).filter(layerFilter)); }, []); const onClick = useCallback(event => { const feature = event.features && event.features[0]; if (feature) { window.alert(`Clicked layer ${feature.layer.id}`); // eslint-disable-line no-alert } }, []); const onMouseEnter = useCallback(() => setCursor('pointer'), []); const onMouseLeave = useCallback(() => setCursor('auto'), []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/custom-cursor/src/control-panel.tsx ================================================ import * as React from 'react'; import {useState, useEffect} from 'react'; // Layer id patterns by category const layerSelector = { parks: /park/, buildings: /building/, roads: /bridge|road|tunnel/, labels: /label|place|poi/ }; function getLayerFilter(categories, layerId) { for (const key in categories) { if (categories[key] && layerSelector[key].test(layerId)) { return true; } } return false; } function Checkbox({name, value, onChange}) { return (
onChange(name, evt.target.checked)} />
); } function StyleControls(props) { const [categories, setCategories] = useState({ parks: true, buildings: true, roads: true, labels: true }); useEffect(() => { const filter = layerId => getLayerFilter(categories, layerId); props.onChange(filter); }, [categories]); const toggleLayer = (name, on) => { setCategories({...categories, [name]: on}); }; return (

Custom Cursor

Customize the cursor based on interactivity.


Clickable layers

{Object.keys(layerSelector).map(name => ( ))}
); } export default React.memo(StyleControls); ================================================ FILE: examples/mapbox/custom-cursor/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/custom-cursor/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/custom-overlay/README.md ================================================ # Example: SVG overlay This app shows how to implement a custom control that draws arbitrary React content that responds to camera updates. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/custom-overlay/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/custom-overlay/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "d3-shape": "^3.1.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/custom-overlay/src/app.tsx ================================================ import * as React from 'react'; import {useMemo, useState} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import {arc, pie} from 'd3-shape'; import CustomOverlay from './custom-overlay'; import ControlPanel, {COLORS} from './control-panel'; import electionData from '../../../.data/us-election-2016.json'; import type {Map as MapboxMap} from 'mapbox-gl'; const TOKEN = ''; // Set your mapbox token here // Shape of the sample data type CountyElectionData = { dem: number; rep: number; total: number; name: string; coordinates: [number, number]; }; export default function App() { return ( <> ); } function PieCharts({map, data}: {map?: MapboxMap; data: any[]}) { const [hoveredCounty, setHoveredCounty] = useState(null); const width = map.getContainer().clientWidth; const height = map.getContainer().clientHeight; // Create pie chart shapes for each row const pies = useMemo(() => data.map(d => makePieChart(d, setHoveredCounty)), [map, data]); // Position each pie chart at the map location const [originLngLat, content] = useMemo(() => { const scale = 2 ** Math.max(0, map.getZoom() - 6); return [ map.unproject([0, 0]), data.map((d, i) => { const centroid = map.project(d.coordinates); return ( {pies[i]} ); }) ]; }, [map.getZoom(), pies]); const origin = map.project(originLngLat); let tooltip; if (hoveredCounty) { const {dem = 0, rep = 0, total, coordinates, name} = hoveredCounty; const tooltipLocation = map.project(coordinates); tooltip = (
{name}
Democrats: {dem} ({((dem / total) * 100).toPrecision(3)}%)
Republican: {rep} ({((rep / total) * 100).toPrecision(3)}%)
); } return ( <> {content} {tooltip} ); } function makePieChart(datum: CountyElectionData, onHover: (target: CountyElectionData) => void) { const {dem = 0, rep = 0, total} = datum; const pathGenerator = arc(); const arcs = pie()([dem, rep, total - dem - rep]); const radius = Math.sqrt(total) / 60; return ( onHover(datum)} onMouseOut={() => onHover(null)} > {arcs.map((a, i) => ( ))} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/custom-overlay/src/control-panel.tsx ================================================ import * as React from 'react'; export const COLORS = ['#2b83ba', '#c7191c', '#c8c8cf']; const legendStyle = { display: 'inline-block', width: 16, height: 8, marginRight: 4 }; function ControlPanel() { return (

US Presidential Election 2016 By County

Democrat
Republican
Independent

Data source: Harvard Dataverse

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/custom-overlay/src/custom-overlay.tsx ================================================ import * as React from 'react'; import {useState, cloneElement} from 'react'; import {useControl} from 'react-map-gl/mapbox'; import {createPortal} from 'react-dom'; import type {IControl, MapInstance} from 'react-map-gl/mapbox'; // Based on template in https://docs.mapbox.com/mapbox-gl-js/api/markers/#icontrol class OverlayControl implements IControl { _map: MapInstance = null; _container: HTMLElement; _redraw: () => void; constructor(redraw: () => void) { this._redraw = redraw; } onAdd(map) { this._map = map; map.on('move', this._redraw); /* global document */ this._container = document.createElement('div'); this._redraw(); return this._container; } onRemove() { this._container.remove(); this._map.off('move', this._redraw); this._map = null; } getMap() { return this._map; } getElement() { return this._container; } } /** * A custom control that rerenders arbitrary React content whenever the camera changes */ function CustomOverlay(props: {children: React.ReactElement}) { const [, setVersion] = useState(0); const ctrl = useControl(() => { const forceUpdate = () => setVersion(v => v + 1); return new OverlayControl(forceUpdate); }); const map = ctrl.getMap(); return map && createPortal(cloneElement(props.children, {map}), ctrl.getElement()); } export default React.memo(CustomOverlay); ================================================ FILE: examples/mapbox/custom-overlay/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/custom-overlay/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/deckgl-overlay/README.md ================================================ # Example: DeckGL Overlay This example demonstrates using [deck.gl](https://deck.gl) to render a data overlay on top of react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/deckgl-overlay/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/deckgl-overlay/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "deck.gl": "^8.8.0-beta.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/deckgl-overlay/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {ArcLayer} from '@deck.gl/layers/typed'; import {DeckProps, PickingInfo} from '@deck.gl/core/typed'; import {MapboxOverlay} from '@deck.gl/mapbox/typed'; import Map, {useControl, NavigationControl} from 'react-map-gl/mapbox'; const TOKEN = ''; // Set your mapbox token here const initialViewState = { latitude: 37.78, longitude: -122.45, zoom: 12, pitch: 45 }; function DeckGLOverlay(props: DeckProps) { const deck = useControl(() => new MapboxOverlay(props)); deck.setProps(props); return null; } // Type of elements in https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-segments.json type DataT = { inbound: number; outbound: number; from: { name: string; coordinates: [number, number]; }; to: { name: string; coordinates: [number, number]; }; }; export default function App() { const arcLayer = new ArcLayer({ data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-segments.json', getSourcePosition: d => d.from.coordinates, getTargetPosition: d => d.to.coordinates, getSourceColor: [255, 200, 0], getTargetColor: [0, 140, 255], getWidth: 12, pickable: true, autoHighlight: true }); return ( ); } function getTooltip(info: PickingInfo) { const d = info.object as DataT; return d && `${d.from.name} -- ${d.to.name}`; } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/deckgl-overlay/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/deckgl-overlay/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/draggable-markers/README.md ================================================ # Example: Draggable Marker Demonstrates how Marker component can be dragged with react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/draggable-markers/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/draggable-markers/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/draggable-markers/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Marker, NavigationControl} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import Pin from './pin'; import type {MarkerDragEvent, LngLat} from 'react-map-gl/mapbox'; const TOKEN = ''; // Set your mapbox token here const initialViewState = { latitude: 40, longitude: -100, zoom: 3.5 }; export default function App() { const [marker, setMarker] = useState({ latitude: 40, longitude: -100 }); const [events, logEvents] = useState>({}); const onMarkerDragStart = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragStart: event.lngLat})); }, []); const onMarkerDrag = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDrag: event.lngLat})); setMarker({ longitude: event.lngLat.lng, latitude: event.lngLat.lat }); }, []); const onMarkerDragEnd = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragEnd: event.lngLat})); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/draggable-markers/src/control-panel.tsx ================================================ import * as React from 'react'; import type {LngLat} from 'react-map-gl/mapbox'; const eventNames = ['onDragStart', 'onDrag', 'onDragEnd']; function round5(value) { return (Math.round(value * 1e5) / 1e5).toFixed(5); } function ControlPanel(props: {events: Record}) { return (

Draggable Marker

Try dragging the marker to another location.

{eventNames.map(eventName => { const {events = {}} = props; const lngLat = events[eventName]; return (
{eventName}:{' '} {lngLat ? `${round5(lngLat.lng)}, ${round5(lngLat.lat)}` : null}
); })}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/draggable-markers/src/pin.tsx ================================================ import * as React from 'react'; const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 C20.1,15.8,20.2,15.8,20.2,15.7z`; const pinStyle = { fill: '#d00', stroke: 'none' }; function Pin(props) { const {size = 20} = props; return ( ); } export default React.memo(Pin); ================================================ FILE: examples/mapbox/draggable-markers/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/draggable-markers/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/draw-polygon/README.md ================================================ # Example: Draw Polygon This app reproduces Mapbox's [Draw a polygon and calculate its area](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/) example. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/draw-polygon/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/draw-polygon/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@mapbox/mapbox-gl-draw": "^1.3.0", "@types/mapbox__mapbox-gl-draw": "^1.2.3", "@turf/area": "^6.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/draw-polygon/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import DrawControl from './draw-control'; import ControlPanel from './control-panel'; const TOKEN = ''; // Set your mapbox token here export default function App() { const [features, setFeatures] = useState({}); const onUpdate = useCallback(e => { setFeatures(currFeatures => { const newFeatures = {...currFeatures}; for (const f of e.features) { newFeatures[f.id] = f; } return newFeatures; }); }, []); const onDelete = useCallback(e => { setFeatures(currFeatures => { const newFeatures = {...currFeatures}; for (const f of e.features) { delete newFeatures[f.id]; } return newFeatures; }); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/draw-polygon/src/control-panel.tsx ================================================ import * as React from 'react'; import area from '@turf/area'; function ControlPanel(props) { let polygonArea = 0; for (const polygon of props.polygons) { polygonArea += area(polygon); } return (

Draw Polygon

{polygonArea > 0 && (

{Math.round(polygonArea * 100) / 100}
square meters

)}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/draw-polygon/src/draw-control.ts ================================================ import MapboxDraw from '@mapbox/mapbox-gl-draw'; import {useControl} from 'react-map-gl/mapbox'; import type {ControlPosition} from 'react-map-gl/mapbox'; type DrawControlProps = ConstructorParameters[0] & { position?: ControlPosition; onCreate?: (evt: {features: object[]}) => void; onUpdate?: (evt: {features: object[]; action: string}) => void; onDelete?: (evt: {features: object[]}) => void; }; export default function DrawControl(props: DrawControlProps) { useControl( () => new MapboxDraw(props), ({map}) => { map.on('draw.create', props.onCreate); map.on('draw.update', props.onUpdate); map.on('draw.delete', props.onDelete); }, ({map}) => { map.off('draw.create', props.onCreate); map.off('draw.update', props.onUpdate); map.off('draw.delete', props.onDelete); }, { position: props.position } ); return null; } DrawControl.defaultProps = { onCreate: () => {}, onUpdate: () => {}, onDelete: () => {} }; ================================================ FILE: examples/mapbox/draw-polygon/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/draw-polygon/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/filter/README.md ================================================ # Example: Highlight By Filter This app reproduces Mapbox's [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) example. This example showcases how to dynamically add/remove filters from layers. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/filter/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/filter/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/filter/src/app.tsx ================================================ import * as React from 'react'; import {useState, useMemo, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Popup, Source, Layer} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import {countiesLayer, highlightLayer} from './map-style'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { const [hoverInfo, setHoverInfo] = useState(null); const onHover = useCallback(event => { const county = event.features && event.features[0]; setHoverInfo({ longitude: event.lngLat.lng, latitude: event.lngLat.lat, countyName: county && county.properties.COUNTY }); }, []); const selectedCounty = (hoverInfo && hoverInfo.countyName) || ''; const filter: ['in', string, string] = useMemo( () => ['in', 'COUNTY', selectedCounty], [selectedCounty] ); return ( <> {selectedCounty && ( {selectedCounty} )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/filter/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Highlight Features Containing Similar Data

Hover over counties to highlight counties that share the same name.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/filter/src/map-style.ts ================================================ import type {FillLayerSpecification} from 'react-map-gl/mapbox'; export const countiesLayer: FillLayerSpecification = { id: 'counties', source: '', type: 'fill', 'source-layer': 'original', paint: { 'fill-outline-color': 'rgba(0,0,0,0.1)', 'fill-color': 'rgba(0,0,0,0.1)' } }; // Highlighted county polygons export const highlightLayer: FillLayerSpecification = { id: 'counties-highlighted', type: 'fill', source: 'counties', 'source-layer': 'original', paint: { 'fill-outline-color': '#484896', 'fill-color': '#6e599f', 'fill-opacity': 0.75 } }; ================================================ FILE: examples/mapbox/filter/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/filter/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/geocoder/README.md ================================================ # Example: Geocoder This app reproduces Mapbox's [Add a geocoder](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-geocoder/) example. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/geocoder/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/geocoder/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@mapbox/mapbox-gl-geocoder": "^4.7.4", "@types/mapbox__mapbox-gl-geocoder": "^4.7.2", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/geocoder/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import GeocoderControl from './geocoder-control'; import ControlPanel from './control-panel'; // eslint-disable-next-line const TOKEN = process.env.MapboxAccessToken; // Set your mapbox token here export default function App() { return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/geocoder/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return ( ); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/geocoder/src/geocoder-control.tsx ================================================ import * as React from 'react'; import {useState} from 'react'; import {useControl, Marker, MarkerProps, ControlPosition} from 'react-map-gl/mapbox'; import MapboxGeocoder, {GeocoderOptions} from '@mapbox/mapbox-gl-geocoder'; import '@mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css'; type GeocoderControlProps = Omit & { mapboxAccessToken: string; marker?: boolean | Omit; position: ControlPosition; onLoading?: (e: object) => void; onResults?: (e: object) => void; onResult?: (e: object) => void; onError?: (e: object) => void; }; /* eslint-disable complexity,max-statements */ export default function GeocoderControl(props: GeocoderControlProps) { const [marker, setMarker] = useState(null); const geocoder = useControl( () => { const ctrl = new MapboxGeocoder({ ...props, marker: false, accessToken: props.mapboxAccessToken }); ctrl.on('loading', props.onLoading); ctrl.on('results', props.onResults); ctrl.on('result', evt => { props.onResult(evt); const {result} = evt; const location = result && (result.center || (result.geometry?.type === 'Point' && result.geometry.coordinates)); if (location && props.marker) { const markerProps = typeof props.marker === 'object' ? props.marker : {}; setMarker(); } else { setMarker(null); } }); ctrl.on('error', props.onError); return ctrl; }, { position: props.position } ); // @ts-ignore (TS2339) private member if (geocoder._map) { if (geocoder.getProximity() !== props.proximity && props.proximity !== undefined) { geocoder.setProximity(props.proximity); } if (geocoder.getRenderFunction() !== props.render && props.render !== undefined) { geocoder.setRenderFunction(props.render); } if (geocoder.getLanguage() !== props.language && props.language !== undefined) { geocoder.setLanguage(props.language); } if (geocoder.getZoom() !== props.zoom && props.zoom !== undefined) { geocoder.setZoom(props.zoom); } if (geocoder.getFlyTo() !== props.flyTo && props.flyTo !== undefined) { geocoder.setFlyTo(props.flyTo); } if (geocoder.getPlaceholder() !== props.placeholder && props.placeholder !== undefined) { geocoder.setPlaceholder(props.placeholder); } if (geocoder.getCountries() !== props.countries && props.countries !== undefined) { geocoder.setCountries(props.countries); } if (geocoder.getTypes() !== props.types && props.types !== undefined) { geocoder.setTypes(props.types); } if (geocoder.getMinLength() !== props.minLength && props.minLength !== undefined) { geocoder.setMinLength(props.minLength); } if (geocoder.getLimit() !== props.limit && props.limit !== undefined) { geocoder.setLimit(props.limit); } if (geocoder.getFilter() !== props.filter && props.filter !== undefined) { geocoder.setFilter(props.filter); } if (geocoder.getOrigin() !== props.origin && props.origin !== undefined) { geocoder.setOrigin(props.origin); } // Types missing from @types/mapbox__mapbox-gl-geocoder // if (geocoder.getAutocomplete() !== props.autocomplete && props.autocomplete !== undefined) { // geocoder.setAutocomplete(props.autocomplete); // } // if (geocoder.getFuzzyMatch() !== props.fuzzyMatch && props.fuzzyMatch !== undefined) { // geocoder.setFuzzyMatch(props.fuzzyMatch); // } // if (geocoder.getRouting() !== props.routing && props.routing !== undefined) { // geocoder.setRouting(props.routing); // } // if (geocoder.getWorldview() !== props.worldview && props.worldview !== undefined) { // geocoder.setWorldview(props.worldview); // } } return marker; } const noop = () => {}; GeocoderControl.defaultProps = { marker: true, onLoading: noop, onResults: noop, onResult: noop, onError: noop }; ================================================ FILE: examples/mapbox/geocoder/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/geocoder/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/geojson/README.md ================================================ # Example: GeoJSON This example showcases how to dynamically add and update custom data sources. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/geojson/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/geojson/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "d3-array": "^3.1.1", "d3-scale": "^4.0.2", "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/geojson/src/app.tsx ================================================ import * as React from 'react'; import {useState, useEffect, useMemo, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Source, Layer} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import {dataLayer} from './map-style'; import {updatePercentiles} from './utils'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { const [year, setYear] = useState(2015); const [allData, setAllData] = useState(null); const [hoverInfo, setHoverInfo] = useState(null); useEffect(() => { /* global fetch */ fetch( 'https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/us-income.geojson' ) .then(resp => resp.json()) .then(json => setAllData(json)) .catch(err => console.error('Could not load data', err)); // eslint-disable-line }, []); const onHover = useCallback(event => { const { features, point: {x, y} } = event; const hoveredFeature = features && features[0]; // prettier-ignore setHoverInfo(hoveredFeature && {feature: hoveredFeature, x, y}); }, []); const data = useMemo(() => { return allData && updatePercentiles(allData, f => f.properties.income[year]); }, [allData, year]); return ( <> {hoverInfo && (
State: {hoverInfo.feature.properties.name}
Median Household Income: {hoverInfo.feature.properties.value}
Percentile: {(hoverInfo.feature.properties.percentile / 8) * 100}
)}
setYear(value)} /> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/geojson/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel(props) { const {year} = props; return (

Interactive GeoJSON

Map showing median household income by state in year {year}. Hover over a state to see details.

Data source:{' '} US Census Bureau


props.onChange(evt.target.value)} />
); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/geojson/src/map-style.ts ================================================ import type {LayerProps} from 'react-map-gl/mapbox'; // For more information on data-driven styles, see https://www.mapbox.com/help/gl-dds-ref/ export const dataLayer: LayerProps = { id: 'data', type: 'fill', paint: { 'fill-color': { type: 'interval', property: 'percentile', stops: [ [0, '#3288bd'], [1, '#66c2a5'], [2, '#abdda4'], [3, '#e6f598'], [4, '#ffffbf'], [5, '#fee08b'], [6, '#fdae61'], [7, '#f46d43'], [8, '#d53e4f'] ] }, 'fill-opacity': 0.8 } }; ================================================ FILE: examples/mapbox/geojson/src/utils.ts ================================================ import {range} from 'd3-array'; import {scaleQuantile} from 'd3-scale'; import type GeoJSON from 'geojson'; export function updatePercentiles( featureCollection: GeoJSON.FeatureCollection, accessor: (f: GeoJSON.Feature) => number ): GeoJSON.FeatureCollection { const {features} = featureCollection; const scale = scaleQuantile().domain(features.map(accessor)).range(range(9)); return { type: 'FeatureCollection', features: features.map(f => { const value = accessor(f); const properties = { ...f.properties, value, percentile: scale(value) }; return {...f, properties}; }) }; } ================================================ FILE: examples/mapbox/geojson/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/geojson/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/geojson-animation/README.md ================================================ # Example: Animated GeoJSON This app reproduces Mapbox's [Animate point along line](https://www.mapbox.com/mapbox-gl-js/example/animate-point-along-line/) example. This example showcases how to dynamically add and update custom data sources. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/geojson-animation/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/geojson-animation/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/geojson-animation/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useEffect} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from 'react-map-gl/mapbox'; import type {LayerProps} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; const MAPBOX_TOKEN = ''; // Set your mapbox token here const pointLayer: LayerProps = { id: 'point', type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; function pointOnCircle({center, angle, radius}) { return { type: 'Point', coordinates: [center[0] + Math.cos(angle) * radius, center[1] + Math.sin(angle) * radius] }; } export default function App() { const [pointData, setPointData] = useState(null); useEffect(() => { const animation = window.requestAnimationFrame(() => setPointData(pointOnCircle({center: [-100, 0], angle: Date.now() / 1000, radius: 20})) ); return () => window.cancelAnimationFrame(animation); }); return ( <> {pointData && ( )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/geojson-animation/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Animated GeoJSON

Render animation by updating GeoJSON data source.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/geojson-animation/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/geojson-animation/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/heatmap/README.md ================================================ # Example: Heatmap layer This app reproduces Mapbox's [Create a heatmap layer](https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/) example. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/heatmap/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/heatmap/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/heatmap/src/app.tsx ================================================ import * as React from 'react'; import {useState, useEffect, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import MapGL, {Source, Layer} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import {heatmapLayer} from './map-style'; const MAPBOX_TOKEN = ''; // Set your mapbox token here function filterFeaturesByDay(featureCollection, time) { const date = new Date(time); const year = date.getFullYear(); const month = date.getMonth(); const day = date.getDate(); const features = featureCollection.features.filter(feature => { const featureDate = new Date(feature.properties.time); return ( featureDate.getFullYear() === year && featureDate.getMonth() === month && featureDate.getDate() === day ); }); return {type: 'FeatureCollection', features}; } export default function App() { const [allDays, useAllDays] = useState(true); const [timeRange, setTimeRange] = useState([0, 0]); const [selectedTime, selectTime] = useState(0); const [earthquakes, setEarthQuakes] = useState(null); useEffect(() => { /* global fetch */ fetch('https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson') .then(resp => resp.json()) .then(json => { // Note: In a real application you would do a validation of JSON data before doing anything with it, // but for demonstration purposes we ingore this part here and just trying to select needed data... const features = json.features; const endTime = features[0].properties.time; const startTime = features[features.length - 1].properties.time; setTimeRange([startTime, endTime]); setEarthQuakes(json); selectTime(endTime); }) .catch(err => console.error('Could not load data', err)); // eslint-disable-line }, []); const data = useMemo(() => { return allDays ? earthquakes : filterFeaturesByDay(earthquakes, selectedTime); }, [earthquakes, allDays, selectedTime]); return ( <> {data && ( )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/heatmap/src/control-panel.tsx ================================================ import * as React from 'react'; function formatTime(time) { const date = new Date(time); return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; } function ControlPanel(props) { const {startTime, endTime, onChangeTime, allDays, onChangeAllDays, selectedTime} = props; const day = 24 * 60 * 60 * 1000; const days = Math.round((endTime - startTime) / day); const selectedDay = Math.round((selectedTime - startTime) / day); const onSelectDay = evt => { const daysToAdd = evt.target.value; // add selected days to start time to calculate new time const newTime = startTime + daysToAdd * day; onChangeTime(newTime); }; return (

Heatmap

Map showing earthquakes
from {formatTime(startTime)} to {formatTime(endTime)}.


onChangeAllDays(evt.target.checked)} />

Data source:{' '} earthquakes.geojson

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/heatmap/src/map-style.ts ================================================ import type {LayerProps} from 'react-map-gl/mapbox'; const MAX_ZOOM_LEVEL = 9; export const heatmapLayer: LayerProps = { id: 'heatmap', maxzoom: MAX_ZOOM_LEVEL, type: 'heatmap', paint: { // Increase the heatmap weight based on frequency and property magnitude 'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1], // Increase the heatmap color weight weight by zoom level // heatmap-intensity is a multiplier on top of heatmap-weight 'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, MAX_ZOOM_LEVEL, 3], // Color ramp for heatmap. Domain is 0 (low) to 1 (high). // Begin color ramp at 0-stop with a 0-transparancy color // to create a blur-like effect. 'heatmap-color': [ 'interpolate', ['linear'], ['heatmap-density'], 0, 'rgba(33,102,172,0)', 0.2, 'rgb(103,169,207)', 0.4, 'rgb(209,229,240)', 0.6, 'rgb(253,219,199)', 0.8, 'rgb(239,138,98)', 0.9, 'rgb(255,201,101)' ], // Adjust the heatmap radius by zoom level 'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, MAX_ZOOM_LEVEL, 20], // Transition from heatmap to circle layer by zoom level 'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0] } }; ================================================ FILE: examples/mapbox/heatmap/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/heatmap/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/interaction/README.md ================================================ # Example: Interaction This example showcases how to toggle/limit user interaction. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/interaction/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/interaction/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/interaction/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; const MAPBOX_TOKEN = ''; // Set your mapbox token here const initialViewState = { latitude: 37.729, longitude: -122.36, zoom: 11, bearing: 0, pitch: 50 }; export default function App() { const [settings, setSettings] = useState({ scrollZoom: true, boxZoom: true, dragRotate: true, dragPan: true, keyboard: true, doubleClickZoom: true, touchZoomRotate: true, touchPitch: true, minZoom: 0, maxZoom: 20, minPitch: 0, maxPitch: 85 }); const updateSettings = useCallback( (name, value) => setSettings(s => ({ ...s, [name]: value })), [] ); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/interaction/src/control-panel.tsx ================================================ import * as React from 'react'; const camelPattern = /(^|[A-Z])[a-z]*/g; function formatSettingName(name) { return name.match(camelPattern).join(' '); } function Checkbox({name, value, onChange}) { return (
onChange(name, evt.target.checked)} />
); } function NumericInput({name, value, onChange}) { return (
onChange(name, Number(evt.target.value))} />
); } function ControlPanel(props) { const {settings, onChange} = props; const renderSetting = (name, value) => { switch (typeof value) { case 'boolean': return ; case 'number': return ; default: return null; } }; return (

Limit Map Interaction

Turn interactive features off/on.


{Object.keys(settings).map(name => renderSetting(name, settings[name]))}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/interaction/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/interaction/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/layers/README.md ================================================ # Example: Layers This example showcases how to dynamically change layer styles and show/hide layers. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/layers/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/layers/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "immutable": "^4.0.0", "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/layers/src/app.tsx ================================================ import * as React from 'react'; import {useState} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; const MAPBOX_TOKEN = ''; // Set your mapbox token here export default function App() { const [mapStyle, setMapStyle] = useState(null); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/layers/src/control-panel.tsx ================================================ import * as React from 'react'; import {useState, useEffect} from 'react'; import {fromJS} from 'immutable'; import MAP_STYLE from '../../map-style-basic-v8.json'; const defaultMapStyle: any = fromJS(MAP_STYLE); const defaultLayers = defaultMapStyle.get('layers'); const categories = ['labels', 'roads', 'buildings', 'parks', 'water', 'background']; // Layer id patterns by category const layerSelector = { background: /background/, water: /water/, parks: /park/, buildings: /building/, roads: /bridge|road|tunnel/, labels: /label|place|poi/ }; // Layer color class by type const colorClass = { line: 'line-color', fill: 'fill-color', background: 'background-color', symbol: 'text-color' }; function getMapStyle({visibility, color}) { const layers = defaultLayers .filter(layer => { const id = layer.get('id'); return categories.every(name => visibility[name] || !layerSelector[name].test(id)); }) .map(layer => { const id = layer.get('id'); const type = layer.get('type'); const category = categories.find(name => layerSelector[name].test(id)); if (category && colorClass[type]) { return layer.setIn(['paint', colorClass[type]], color[category]); } return layer; }); return defaultMapStyle.set('layers', layers); } function StyleControls(props) { const [visibility, setVisibility] = useState({ water: true, parks: true, buildings: true, roads: true, labels: true, background: true }); const [color, setColor] = useState({ water: '#DBE2E6', parks: '#E6EAE9', buildings: '#c0c0c8', roads: '#ffffff', labels: '#78888a', background: '#EBF0F0' }); useEffect(() => { props.onChange(getMapStyle({visibility, color})); }, [visibility, color]); const onColorChange = (name, value) => { setColor({...color, [name]: value}); }; const onVisibilityChange = (name, value) => { setVisibility({...visibility, [name]: value}); }; return (

Dynamic Styling

Dynamically show/hide map layers and change color with Immutable map style.


{categories.map(name => (
onVisibilityChange(name, evt.target.checked)} /> onColorChange(name, evt.target.value)} />
))}
); } export default React.memo(StyleControls); ================================================ FILE: examples/mapbox/layers/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/layers/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/map-style-basic-v8.json ================================================ { "version": 8, "name": "Basic", "metadata": { "mapbox:autocomposite": true }, "sources": { "mapbox": { "url": "mapbox://mapbox.mapbox-streets-v7", "type": "vector" } }, "sprite": "mapbox://sprites/mapbox/basic-v8", "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf", "layers": [ { "id": "background", "type": "background", "paint": { "background-color": "#dedede" }, "interactive": true }, { "id": "landuse_overlay_national_park", "type": "fill", "source": "mapbox", "source-layer": "landuse_overlay", "filter": [ "==", "class", "national_park" ], "paint": { "fill-color": "#d2edae", "fill-opacity": 0.75 }, "interactive": true }, { "id": "landuse_park", "type": "fill", "source": "mapbox", "source-layer": "landuse", "filter": [ "==", "class", "park" ], "paint": { "fill-color": "#d2edae" }, "interactive": true }, { "id": "waterway", "type": "line", "source": "mapbox", "source-layer": "waterway", "filter": [ "all", [ "==", "$type", "LineString" ], [ "in", "class", "river", "canal" ] ], "paint": { "line-color": "#a0cfdf", "line-width": { "base": 1.4, "stops": [ [ 8, 0.5 ], [ 20, 15 ] ] } }, "interactive": true }, { "id": "water", "type": "fill", "source": "mapbox", "source-layer": "water", "paint": { "fill-color": "#a0cfdf" }, "interactive": true }, { "id": "building", "type": "fill", "source": "mapbox", "source-layer": "building", "paint": { "fill-color": "#d6d6d6" }, "interactive": true }, { "interactive": true, "layout": { "line-cap": "butt", "line-join": "miter" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway_link", "street", "street_limited", "service", "track", "pedestrian", "path", "link" ], [ "==", "structure", "tunnel" ] ] ], "type": "line", "source": "mapbox", "id": "tunnel_minor", "paint": { "line-color": "#efefef", "line-width": { "base": 1.55, "stops": [ [ 4, 0.25 ], [ 20, 30 ] ] }, "line-dasharray": [ 0.36, 0.18 ] }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "butt", "line-join": "miter" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway", "primary", "secondary", "tertiary", "trunk" ], [ "==", "structure", "tunnel" ] ] ], "type": "line", "source": "mapbox", "id": "tunnel_major", "paint": { "line-color": "#fff", "line-width": { "base": 1.4, "stops": [ [ 6, 0.5 ], [ 20, 30 ] ] }, "line-dasharray": [ 0.28, 0.14 ] }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "round", "line-join": "round" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway_link", "street", "street_limited", "service", "track", "pedestrian", "path", "link" ], [ "in", "structure", "none", "ford" ] ] ], "type": "line", "source": "mapbox", "id": "road_minor", "paint": { "line-color": "#efefef", "line-width": { "base": 1.55, "stops": [ [ 4, 0.25 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "round", "line-join": "round" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway", "primary", "secondary", "tertiary", "trunk" ], [ "in", "structure", "none", "ford" ] ] ], "type": "line", "source": "mapbox", "id": "road_major", "paint": { "line-color": "#fff", "line-width": { "base": 1.4, "stops": [ [ 6, 0.5 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "butt", "line-join": "miter" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway_link", "street", "street_limited", "service", "track", "pedestrian", "path", "link" ], [ "==", "structure", "bridge" ] ] ], "type": "line", "source": "mapbox", "id": "bridge_minor case", "paint": { "line-color": "#dedede", "line-width": { "base": 1.6, "stops": [ [ 12, 0.5 ], [ 20, 10 ] ] }, "line-gap-width": { "base": 1.55, "stops": [ [ 4, 0.25 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "butt", "line-join": "miter" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway", "primary", "secondary", "tertiary", "trunk" ], [ "==", "structure", "bridge" ] ] ], "type": "line", "source": "mapbox", "id": "bridge_major case", "paint": { "line-color": "#dedede", "line-width": { "base": 1.6, "stops": [ [ 12, 0.5 ], [ 20, 10 ] ] }, "line-gap-width": { "base": 1.55, "stops": [ [ 4, 0.25 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "round", "line-join": "round" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway_link", "street", "street_limited", "service", "track", "pedestrian", "path", "link" ], [ "==", "structure", "bridge" ] ] ], "type": "line", "source": "mapbox", "id": "bridge_minor", "paint": { "line-color": "#efefef", "line-width": { "base": 1.55, "stops": [ [ 4, 0.25 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "round", "line-join": "round" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "in", "class", "motorway", "primary", "secondary", "tertiary", "trunk" ], [ "==", "structure", "bridge" ] ] ], "type": "line", "source": "mapbox", "id": "bridge_major", "paint": { "line-color": "#fff", "line-width": { "base": 1.4, "stops": [ [ 6, 0.5 ], [ 20, 30 ] ] } }, "source-layer": "road" }, { "interactive": true, "layout": { "line-cap": "round", "line-join": "round" }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "all", [ "<=", "admin_level", 2 ], [ "==", "maritime", 0 ] ] ], "type": "line", "source": "mapbox", "id": "admin_country", "paint": { "line-color": "#8b8a8a", "line-width": { "base": 1.3, "stops": [ [ 3, 0.5 ], [ 22, 15 ] ] } }, "source-layer": "admin" }, { "interactive": true, "minzoom": 5, "layout": { "icon-image": "{maki}-11", "text-offset": [ 0, 0.5 ], "text-field": "{name_en}", "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], "text-max-width": 8, "text-anchor": "top", "text-size": 11, "icon-size": 1 }, "filter": [ "all", [ "==", "$type", "Point" ], [ "all", [ "==", "scalerank", 1 ], [ "==", "localrank", 1 ] ] ], "type": "symbol", "source": "mapbox", "id": "poi_label", "paint": { "text-color": "#666", "text-halo-width": 1, "text-halo-color": "rgba(255,255,255,0.75)", "text-halo-blur": 1 }, "source-layer": "poi_label" }, { "interactive": true, "layout": { "symbol-placement": "line", "text-field": "{name_en}", "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], "text-transform": "uppercase", "text-letter-spacing": 0.1, "text-size": { "base": 1.4, "stops": [ [ 10, 8 ], [ 20, 14 ] ] } }, "filter": [ "all", [ "==", "$type", "LineString" ], [ "in", "class", "motorway", "primary", "secondary", "tertiary", "trunk" ] ], "type": "symbol", "source": "mapbox", "id": "road_major_label", "paint": { "text-color": "#666", "text-halo-color": "rgba(255,255,255,0.75)", "text-halo-width": 2 }, "source-layer": "road_label" }, { "interactive": true, "minzoom": 8, "layout": { "text-field": "{name_en}", "text-font": [ "Open Sans Semibold", "Arial Unicode MS Bold" ], "text-max-width": 6, "text-size": { "stops": [ [ 6, 12 ], [ 12, 16 ] ] } }, "filter": [ "all", [ "==", "$type", "Point" ], [ "in", "type", "town", "village", "hamlet", "suburb", "neighbourhood", "island" ] ], "type": "symbol", "source": "mapbox", "id": "place_label_other", "paint": { "text-color": "#666", "text-halo-color": "rgba(255,255,255,0.75)", "text-halo-width": 1, "text-halo-blur": 1 }, "source-layer": "place_label" }, { "interactive": true, "layout": { "text-field": "{name_en}", "text-font": [ "Open Sans Bold", "Arial Unicode MS Bold" ], "text-max-width": 10, "text-size": { "stops": [ [ 3, 12 ], [ 8, 16 ] ] } }, "maxzoom": 16, "filter": [ "all", [ "==", "$type", "Point" ], [ "==", "type", "city" ] ], "type": "symbol", "source": "mapbox", "id": "place_label_city", "paint": { "text-color": "#666", "text-halo-color": "rgba(255,255,255,0.75)", "text-halo-width": 1, "text-halo-blur": 1 }, "source-layer": "place_label" }, { "interactive": true, "layout": { "text-field": "{name_en}", "text-font": [ "Open Sans Regular", "Arial Unicode MS Regular" ], "text-max-width": 10, "text-size": { "stops": [ [ 3, 14 ], [ 8, 22 ] ] } }, "maxzoom": 12, "filter": [ "==", "$type", "Point" ], "type": "symbol", "source": "mapbox", "id": "country_label", "paint": { "text-color": "#666", "text-halo-color": "rgba(255,255,255,0.75)", "text-halo-width": 1, "text-halo-blur": 1 }, "source-layer": "country_label" } ] } ================================================ FILE: examples/mapbox/side-by-side/README.md ================================================ # Example: Side By Side Demonstrates how to synchronize two maps with react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/side-by-side/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/side-by-side/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/side-by-side/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useCallback, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import ControlPanel, {Mode} from './control-panel'; const TOKEN = ''; // Set your mapbox token here const LeftMapStyle: React.CSSProperties = { position: 'absolute', width: '50%', height: '100%' }; const RightMapStyle: React.CSSProperties = { position: 'absolute', left: '50%', width: '50%', height: '100%' }; export default function App() { const [viewState, setViewState] = useState({ longitude: -122.43, latitude: 37.78, zoom: 12, pitch: 30 }); const [mode, setMode] = useState('side-by-side'); // Two maps could be firing 'move' events at the same time, if the user interacts with one // while the other is in transition. // This state specifies which map to use as the source of truth // It is set to the map that received user input last ('movestart') const [activeMap, setActiveMap] = useState<'left' | 'right'>('left'); const onLeftMoveStart = useCallback(() => setActiveMap('left'), []); const onRightMoveStart = useCallback(() => setActiveMap('right'), []); const onMove = useCallback(evt => setViewState(evt.viewState), []); const width = typeof window === 'undefined' ? 100 : window.innerWidth; const leftMapPadding = useMemo(() => { return {left: mode === 'split-screen' ? width / 2 : 0, top: 0, right: 0, bottom: 0}; }, [width, mode]); const rightMapPadding = useMemo(() => { return {right: mode === 'split-screen' ? width / 2 : 0, top: 0, left: 0, bottom: 0}; }, [width, mode]); return ( <>
); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/side-by-side/src/control-panel.tsx ================================================ import * as React from 'react'; import {useCallback} from 'react'; export type Mode = 'side-by-side' | 'split-screen'; function ControlPanel(props: {mode: Mode; onModeChange: (newMode: Mode) => void}) { const onModeChange = useCallback( evt => { props.onModeChange(evt.target.value as Mode); }, [props.onModeChange] ); return (

Side by Side

Synchronize two maps.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/side-by-side/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/side-by-side/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/terrain/README.md ================================================ # Example: 3D Terrain Demonstrates how to add 3D terrain with react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/terrain/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/terrain/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/terrain/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import Map, {Source, Layer} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; import type {SkyLayerSpecification} from 'react-map-gl/mapbox'; const TOKEN = ''; // Set your mapbox token here const skyLayer: SkyLayerSpecification = { id: 'sky', type: 'sky', paint: { 'sky-type': 'atmosphere', 'sky-atmosphere-sun': [0.0, 0.0], 'sky-atmosphere-sun-intensity': 15 } }; export default function App() { return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/terrain/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

3D Terrain

Add 3D terrain and sky to a map.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/terrain/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/terrain/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/viewport-animation/README.md ================================================ # Example: Viewport Animation This example showcases how to transition smoothly between one viewport to another. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/viewport-animation/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/viewport-animation/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "mapbox-gl": "^3.5.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/viewport-animation/src/app.tsx ================================================ import * as React from 'react'; import {useRef, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import Map, {MapRef} from 'react-map-gl/mapbox'; import ControlPanel from './control-panel'; const MAPBOX_TOKEN = ''; // Set your mapbox token here const initialViewState = { latitude: 37.7751, longitude: -122.4193, zoom: 11, bearing: 0, pitch: 0 }; export default function App() { const mapRef = useRef(); const onSelectCity = useCallback(({longitude, latitude}) => { mapRef.current?.flyTo({center: [longitude, latitude], duration: 2000}); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/viewport-animation/src/control-panel.tsx ================================================ import * as React from 'react'; import CITIES from '../../../.data/cities.json'; function ControlPanel(props) { return (

Camera Transition

Smooth animate of the viewport.


{CITIES.filter(city => city.state === 'California').map((city, index) => (
props.onSelectCity(city)} />
))}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/viewport-animation/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/viewport-animation/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/mapbox/zoom-to-bounds/README.md ================================================ # Example: Zoom To Bounds Demonstrates how to zoom to a bounding box with react-map-gl. ## Usage To run this example, you need a [Mapbox token](http://visgl.github.io/react-map-gl/docs/get-started/mapbox-tokens). You can either set it as `MAPBOX_TOKEN` in `src/app.js`, or set a `MapboxAccessToken` environment variable in the command line. ```bash npm i npm run start ``` Alternative to acquiring a Mapbox token, you can use `maplibre-gl` instead. Follow these steps: - Run `npm install maplibre-gl` - In the source, change all `import ... from 'react-map-gl/mapbox'` to `import ... from 'react-map-gl/maplibre'` - Change the `mapStyle` prop of `` to `"https://demotiles.maplibre.org/style.json"` or a self-hosted URL ================================================ FILE: examples/mapbox/zoom-to-bounds/index.html ================================================ react-map-gl Example
================================================ FILE: examples/mapbox/zoom-to-bounds/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@turf/bbox": "^6.5.0", "mapbox-gl": "^3.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/mapbox/zoom-to-bounds/src/app.tsx ================================================ import * as React from 'react'; import {useRef} from 'react'; import {createRoot} from 'react-dom/client'; import Map from 'react-map-gl/mapbox'; import bbox from '@turf/bbox'; import ControlPanel from './control-panel'; import MAP_STYLE from './map-style'; import type {MapStyle, MapRef, MapLayerMouseEvent} from 'react-map-gl/mapbox'; const TOKEN = ''; // Set your mapbox token here export default function App() { const mapRef = useRef(); const onClick = (event: MapLayerMouseEvent) => { const feature = event.features[0]; if (feature) { // calculate the bounding box of the feature const [minLng, minLat, maxLng, maxLat] = bbox(feature); mapRef.current.fitBounds( [ [minLng, minLat], [maxLng, maxLat] ], {padding: 40, duration: 1000} ); } }; return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/mapbox/zoom-to-bounds/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Zoom to Bounding Box

Click on a San Fransisco Neighborhood to zoom in.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/mapbox/zoom-to-bounds/src/map-style.tsx ================================================ import type { GeoJSONSourceSpecification, FillLayerSpecification, LineLayerSpecification } from 'react-map-gl/mapbox'; import MAP_STYLE from '../../map-style-basic-v8.json'; const sfNeighborhoods: GeoJSONSourceSpecification = { type: 'geojson', data: 'https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/feature-example-sf.json' }; const fillLayer: FillLayerSpecification = { id: 'sf-neighborhoods-fill', source: 'sf-neighborhoods', type: 'fill', paint: { 'fill-outline-color': '#0040c8', 'fill-color': '#fff', 'fill-opacity': 0 } }; const lineLayer: LineLayerSpecification = { id: 'sf-neighborhoods-outline', source: 'sf-neighborhoods', type: 'line', paint: { 'line-width': 2, 'line-color': '#0080ef' } }; // Make a copy of the map style export default { ...MAP_STYLE, sources: { ...MAP_STYLE.sources, ['sf-neighborhoods']: sfNeighborhoods }, layers: [...MAP_STYLE.layers, fillLayer, lineLayer] }; ================================================ FILE: examples/mapbox/zoom-to-bounds/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/mapbox/zoom-to-bounds/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: examples/maplibre/clusters/README.md ================================================ # Example: Supercluster This app reproduces Maplibre's [Create and style clusters](https://maplibre.org/maplibre-gl-js/docs/examples/cluster/) example. This example showcases how to visualize points as clusters. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/clusters/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/clusters/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/clusters/src/app.tsx ================================================ import * as React from 'react'; import {useRef} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import {clusterLayer, clusterCountLayer, unclusteredPointLayer} from './layers'; import type {MapRef, MapMouseEvent} from 'react-map-gl/maplibre'; import type {GeoJSONSource} from 'maplibre-gl'; export default function App() { const mapRef = useRef(null); const onClick = async (event: MapMouseEvent) => { const feature = event.features[0]; if (!feature) { return; } const clusterId = feature.properties.cluster_id; const geojsonSource: GeoJSONSource = mapRef.current.getSource('earthquakes'); const zoom = await geojsonSource.getClusterExpansionZoom(clusterId); mapRef.current.easeTo({ center: feature.geometry.coordinates, zoom, duration: 500 }); }; return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/clusters/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Create and Style Clusters

Use Maplibre GL JS' built-in functions to visualize points as clusters.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/clusters/src/layers.ts ================================================ import type {LayerProps} from 'react-map-gl/maplibre'; export const clusterLayer: LayerProps = { id: 'clusters', type: 'circle', source: 'earthquakes', filter: ['has', 'point_count'], paint: { 'circle-color': ['step', ['get', 'point_count'], '#51bbd6', 100, '#f1f075', 750, '#f28cb1'], 'circle-radius': ['step', ['get', 'point_count'], 20, 100, 30, 750, 40] } }; export const clusterCountLayer: LayerProps = { id: 'cluster-count', type: 'symbol', source: 'earthquakes', filter: ['has', 'point_count'], layout: { 'text-field': '{point_count_abbreviated}', 'text-size': 12 } }; export const unclusteredPointLayer: LayerProps = { id: 'unclustered-point', type: 'circle', source: 'earthquakes', filter: ['!', ['has', 'point_count']], paint: { 'circle-color': '#11b4da', 'circle-radius': 4, 'circle-stroke-width': 1, 'circle-stroke-color': '#fff' } }; ================================================ FILE: examples/maplibre/clusters/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/controls/README.md ================================================ # Example: Controls Demonstrates how various control components can be used with react-maplibre. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/controls/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/controls/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/controls/src/app.tsx ================================================ import * as React from 'react'; import {useState, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import { Map, Marker, Popup, NavigationControl, FullscreenControl, ScaleControl, GeolocateControl } from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import Pin from './pin'; import CITIES from '../../../.data/cities.json'; export default function App() { const [popupInfo, setPopupInfo] = useState(null); const pins = useMemo( () => CITIES.map((city, index) => ( { // If we let the click event propagates to the map, it will immediately close the popup // with `closeOnClick: true` e.originalEvent.stopPropagation(); setPopupInfo(city); }} > )), [] ); return ( <> {pins} {popupInfo && ( setPopupInfo(null)} >
{popupInfo.city}, {popupInfo.state} |{' '} Wikipedia
)}
); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/controls/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Marker, Popup, NavigationControl and FullscreenControl

Map showing top 20 most populated cities of the United States. Click on a marker to learn more.

Data source:{' '} Wikipedia

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/controls/src/pin.tsx ================================================ import * as React from 'react'; const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 C20.1,15.8,20.2,15.8,20.2,15.7z`; const pinStyle = { cursor: 'pointer', fill: '#d00', stroke: 'none' }; function Pin({size = 20}) { return ( ); } export default React.memo(Pin); ================================================ FILE: examples/maplibre/controls/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/custom-cursor/README.md ================================================ # Example: Custom Cursor This example showcases how to dynamically change the cursor over the map based on interactivity. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/custom-cursor/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/custom-cursor/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/custom-cursor/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, MapStyle} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import MAP_STYLE from '../../map-style-basic-v8.json'; const initialViewState = { longitude: -122.48, latitude: 37.78, zoom: 15.5, bearing: 0, pitch: 0 }; export default function App() { const [cursor, setCursor] = useState('auto'); const [interactiveLayerIds, setInteractiveLayerIds] = useState(['nonexist']); const onInteractiveLayersChange = useCallback(layerFilter => { setInteractiveLayerIds(MAP_STYLE.layers.map(layer => layer.id).filter(layerFilter)); }, []); const onClick = useCallback(event => { const feature = event.features && event.features[0]; if (feature) { window.alert(`Clicked layer ${feature.layer.id}`); // eslint-disable-line no-alert } }, []); const onMouseEnter = useCallback(() => setCursor('pointer'), []); const onMouseLeave = useCallback(() => setCursor('auto'), []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/custom-cursor/src/control-panel.tsx ================================================ import * as React from 'react'; import {useState, useEffect} from 'react'; // Layer id patterns by category const layerSelector = { parks: /park/, buildings: /building/, roads: /bridge|road|tunnel/, labels: /label|place|poi/ }; function getLayerFilter(categories, layerId) { for (const key in categories) { if (categories[key] && layerSelector[key].test(layerId)) { return true; } } return false; } function Checkbox({name, value, onChange}) { return (
onChange(name, evt.target.checked)} />
); } function StyleControls(props) { const [categories, setCategories] = useState({ parks: true, buildings: true, roads: true, labels: true }); useEffect(() => { const filter = layerId => getLayerFilter(categories, layerId); props.onChange(filter); }, [categories]); const toggleLayer = (name, on) => { setCategories({...categories, [name]: on}); }; return (

Custom Cursor

Customize the cursor based on interactivity.


Clickable layers

{Object.keys(layerSelector).map(name => ( ))}
); } export default React.memo(StyleControls); ================================================ FILE: examples/maplibre/custom-cursor/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/custom-overlay/README.md ================================================ # Example: SVG overlay This app shows how to implement a custom control that draws arbitrary React content that responds to camera updates. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/custom-overlay/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/custom-overlay/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "d3-shape": "^3.1.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/custom-overlay/src/app.tsx ================================================ import * as React from 'react'; import {useMemo, useState} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import {arc, pie} from 'd3-shape'; import CustomOverlay from './custom-overlay'; import ControlPanel, {COLORS} from './control-panel'; import electionData from '../../../.data/us-election-2016.json'; import type {Map as MaplibreMap} from 'maplibre-gl'; // Shape of the sample data type CountyElectionData = { dem: number; rep: number; total: number; name: string; coordinates: [number, number]; }; export default function App() { return ( <> ); } function PieCharts({map, data}: {map?: MaplibreMap; data: any[]}) { const [hoveredCounty, setHoveredCounty] = useState(null); const width = map.getContainer().clientWidth; const height = map.getContainer().clientHeight; // Create pie chart shapes for each row const pies = useMemo(() => data.map(d => makePieChart(d, setHoveredCounty)), [map, data]); // Position each pie chart at the map location const [originLngLat, content] = useMemo(() => { const scale = 2 ** Math.max(0, map.getZoom() - 6); return [ map.unproject([0, 0]), data.map((d, i) => { const centroid = map.project(d.coordinates); return ( {pies[i]} ); }) ]; }, [map.getZoom(), pies]); const origin = map.project(originLngLat); let tooltip; if (hoveredCounty) { const {dem = 0, rep = 0, total, coordinates, name} = hoveredCounty; const tooltipLocation = map.project(coordinates); tooltip = (
{name}
Democrats: {dem} ({((dem / total) * 100).toPrecision(3)}%)
Republican: {rep} ({((rep / total) * 100).toPrecision(3)}%)
); } return ( <> {content} {tooltip} ); } function makePieChart(datum: CountyElectionData, onHover: (target: CountyElectionData) => void) { const {dem = 0, rep = 0, total} = datum; const pathGenerator = arc(); const arcs = pie()([dem, rep, total - dem - rep]); const radius = Math.sqrt(total) / 60; return ( onHover(datum)} onMouseOut={() => onHover(null)} > {arcs.map((a, i) => ( ))} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/custom-overlay/src/control-panel.tsx ================================================ import * as React from 'react'; export const COLORS = ['#2b83ba', '#c7191c', '#c8c8cf']; const legendStyle = { display: 'inline-block', width: 16, height: 8, marginRight: 4 }; function ControlPanel() { return (

US Presidential Election 2016 By County

Democrat
Republican
Independent

Data source: Harvard Dataverse

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/custom-overlay/src/custom-overlay.tsx ================================================ import * as React from 'react'; import {useState, cloneElement} from 'react'; import {useControl} from 'react-map-gl/maplibre'; import {createPortal} from 'react-dom'; import type {IControl, MapInstance} from 'react-map-gl/maplibre'; class OverlayControl implements IControl { _map: MapInstance = null; _container: HTMLElement; _redraw: () => void; constructor(redraw: () => void) { this._redraw = redraw; } onAdd(map) { this._map = map; map.on('move', this._redraw); /* global document */ this._container = document.createElement('div'); this._redraw(); return this._container; } onRemove() { this._container.remove(); this._map.off('move', this._redraw); this._map = null; } getMap() { return this._map; } getElement() { return this._container; } } /** * A custom control that rerenders arbitrary React content whenever the camera changes */ function CustomOverlay(props: {children: React.ReactElement}) { const [, setVersion] = useState(0); const ctrl = useControl(() => { const forceUpdate = () => setVersion(v => v + 1); return new OverlayControl(forceUpdate); }); const map = ctrl.getMap(); return map && createPortal(cloneElement(props.children, {map}), ctrl.getElement()); } export default React.memo(CustomOverlay); ================================================ FILE: examples/maplibre/custom-overlay/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/deckgl-overlay/README.md ================================================ # Example: DeckGL Overlay This example demonstrates using [deck.gl](https://deck.gl) to render a data overlay on top of react-maplibre. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/deckgl-overlay/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/deckgl-overlay/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "deck.gl": "^9.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/deckgl-overlay/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {ArcLayer} from '@deck.gl/layers'; import {DeckProps, PickingInfo} from '@deck.gl/core'; import {MapboxOverlay} from '@deck.gl/mapbox'; import {Map, useControl, NavigationControl} from 'react-map-gl/maplibre'; const initialViewState = { latitude: 37.78, longitude: -122.45, zoom: 12, pitch: 45 }; function DeckGLOverlay(props: DeckProps) { const deck = useControl(() => new MapboxOverlay(props)); deck.setProps(props); return null; } // Type of elements in https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-segments.json type DataT = { inbound: number; outbound: number; from: { name: string; coordinates: [number, number]; }; to: { name: string; coordinates: [number, number]; }; }; export default function App() { const arcLayer = new ArcLayer({ data: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/website/bart-segments.json', getSourcePosition: d => d.from.coordinates, getTargetPosition: d => d.to.coordinates, getSourceColor: [255, 200, 0], getTargetColor: [0, 140, 255], getWidth: 12, pickable: true, autoHighlight: true }); return ( ); } function getTooltip(info: PickingInfo) { const d = info.object as DataT; return d && `${d.from.name} -- ${d.to.name}`; } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/deckgl-overlay/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/draggable-markers/README.md ================================================ # Example: Draggable Marker Demonstrates how Marker component can be dragged with react-maplibre. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/draggable-markers/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/draggable-markers/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/draggable-markers/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Marker, NavigationControl} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import Pin from './pin'; import type {MarkerDragEvent, LngLat} from 'react-map-gl/maplibre'; const initialViewState = { latitude: 40, longitude: -100, zoom: 3.5 }; export default function App() { const [marker, setMarker] = useState({ latitude: 40, longitude: -100 }); const [events, logEvents] = useState>({}); const onMarkerDragStart = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragStart: event.lngLat})); }, []); const onMarkerDrag = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDrag: event.lngLat})); setMarker({ longitude: event.lngLat.lng, latitude: event.lngLat.lat }); }, []); const onMarkerDragEnd = useCallback((event: MarkerDragEvent) => { logEvents(_events => ({..._events, onDragEnd: event.lngLat})); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/draggable-markers/src/control-panel.tsx ================================================ import * as React from 'react'; import type {LngLat} from 'react-map-gl/maplibre'; const eventNames = ['onDragStart', 'onDrag', 'onDragEnd']; function round5(value) { return (Math.round(value * 1e5) / 1e5).toFixed(5); } function ControlPanel(props: {events: Record}) { return (

Draggable Marker

Try dragging the marker to another location.

{eventNames.map(eventName => { const {events = {}} = props; const lngLat = events[eventName]; return (
{eventName}:{' '} {lngLat ? `${round5(lngLat.lng)}, ${round5(lngLat.lat)}` : null}
); })}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/draggable-markers/src/pin.tsx ================================================ import * as React from 'react'; const ICON = `M20.2,15.7L20.2,15.7c1.1-1.6,1.8-3.6,1.8-5.7c0-5.6-4.5-10-10-10S2,4.5,2,10c0,2,0.6,3.9,1.6,5.4c0,0.1,0.1,0.2,0.2,0.3 c0,0,0.1,0.1,0.1,0.2c0.2,0.3,0.4,0.6,0.7,0.9c2.6,3.1,7.4,7.6,7.4,7.6s4.8-4.5,7.4-7.5c0.2-0.3,0.5-0.6,0.7-0.9 C20.1,15.8,20.2,15.8,20.2,15.7z`; const pinStyle = { fill: '#d00', stroke: 'none' }; function Pin(props) { const {size = 20} = props; return ( ); } export default React.memo(Pin); ================================================ FILE: examples/maplibre/draggable-markers/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/draw-polygon/README.md ================================================ # Example: Draw Polygon This app reproduces Mapbox's [Draw a polygon and calculate its area](https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-draw/) example. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/draw-polygon/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/draw-polygon/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@mapbox/mapbox-gl-draw": "^1.3.0", "@types/mapbox__mapbox-gl-draw": "^1.2.3", "@turf/area": "^6.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/draw-polygon/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import DrawControl from './draw-control'; import ControlPanel from './control-panel'; import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'; export default function App() { const [features, setFeatures] = useState({}); const onUpdate = useCallback(e => { setFeatures(currFeatures => { const newFeatures = {...currFeatures}; for (const f of e.features) { newFeatures[f.id] = f; } return newFeatures; }); }, []); const onDelete = useCallback(e => { setFeatures(currFeatures => { const newFeatures = {...currFeatures}; for (const f of e.features) { delete newFeatures[f.id]; } return newFeatures; }); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/draw-polygon/src/control-panel.tsx ================================================ import * as React from 'react'; import area from '@turf/area'; function ControlPanel(props) { let polygonArea = 0; for (const polygon of props.polygons) { polygonArea += area(polygon); } return (

Draw Polygon

{polygonArea > 0 && (

{Math.round(polygonArea * 100) / 100}
square meters

)}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/draw-polygon/src/draw-control.ts ================================================ import MapboxDraw from '@mapbox/mapbox-gl-draw'; import {useControl} from 'react-map-gl/maplibre'; import type {ControlPosition} from 'react-map-gl/maplibre'; type DrawControlProps = ConstructorParameters[0] & { position?: ControlPosition; onCreate?: (evt: {features: object[]}) => void; onUpdate?: (evt: {features: object[]; action: string}) => void; onDelete?: (evt: {features: object[]}) => void; }; export default function DrawControl(props: DrawControlProps) { useControl( () => new MapboxDraw(props), ({map}) => { map.on('draw.create', props.onCreate); map.on('draw.update', props.onUpdate); map.on('draw.delete', props.onDelete); }, ({map}) => { map.off('draw.create', props.onCreate); map.off('draw.update', props.onUpdate); map.off('draw.delete', props.onDelete); }, { position: props.position } ); return null; } DrawControl.defaultProps = { onCreate: () => {}, onUpdate: () => {}, onDelete: () => {} }; ================================================ FILE: examples/maplibre/draw-polygon/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/filter/README.md ================================================ # Example: Highlight By Filter This app reproduces Mapbox's [Highlight features containing similar data](https://www.mapbox.com/mapbox-gl-js/example/query-similar-features/) example. This example showcases how to dynamically add/remove filters from layers. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/filter/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/filter/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/filter/src/app.tsx ================================================ import * as React from 'react'; import {useState, useMemo, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Popup, Source, Layer} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import {countiesLayer, highlightLayer} from './map-style'; import type {ExpressionSpecification} from 'maplibre-gl'; export default function App() { const [hoverInfo, setHoverInfo] = useState(null); const onHover = useCallback(event => { const county = event.features && event.features[0]; setHoverInfo({ longitude: event.lngLat.lng, latitude: event.lngLat.lat, countyName: county && county.properties.name.split(',')[0] }); }, []); const selectedCounty = (hoverInfo && hoverInfo.countyName) || ''; const filter: ExpressionSpecification = useMemo( () => ['in', selectedCounty || 'N/A', ['get', 'name']], [selectedCounty] ); return ( <> {selectedCounty && ( {selectedCounty} )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/filter/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Highlight Features Containing Similar Data

Hover over counties to highlight counties that share the same name.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/filter/src/map-style.ts ================================================ import type {FillLayerSpecification} from 'react-map-gl/maplibre'; export const countiesLayer: FillLayerSpecification = { id: 'counties', source: '', type: 'fill', paint: { 'fill-outline-color': 'rgba(0,0,0,0.1)', 'fill-color': 'rgba(0,0,0,0.1)' } }; // Highlighted county polygons export const highlightLayer: FillLayerSpecification = { id: 'counties-highlighted', type: 'fill', source: 'counties', paint: { 'fill-outline-color': '#484896', 'fill-color': '#6e599f', 'fill-opacity': 0.75 } }; ================================================ FILE: examples/maplibre/filter/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/geocoder/README.md ================================================ # Example: Geocoder This app reproduces Maplibre's [Geocode with Nominatim](https://maplibre.org/maplibre-gl-js/docs/examples/geocoder/) example. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/geocoder/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/geocoder/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@maplibre/maplibre-gl-geocoder": "^1.5.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/geocoder/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import GeocoderControl from './geocoder-control'; import ControlPanel from './control-panel'; import '@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css'; export default function App() { return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/geocoder/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return ( ); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/geocoder/src/geocoder-control.tsx ================================================ /* global fetch */ import * as React from 'react'; import {useState} from 'react'; import {useControl, Marker, MarkerProps, ControlPosition} from 'react-map-gl/maplibre'; import MaplibreGeocoder, { MaplibreGeocoderApi, MaplibreGeocoderOptions } from '@maplibre/maplibre-gl-geocoder'; type GeocoderControlProps = Omit & { marker?: boolean | Omit; position: ControlPosition; onLoading?: (e: object) => void; onResults?: (e: object) => void; onResult?: (e: object) => void; onError?: (e: object) => void; }; /* eslint-disable camelcase */ const geocoderApi: MaplibreGeocoderApi = { forwardGeocode: async config => { const features = []; try { const request = `https://nominatim.openstreetmap.org/search?q=${config.query}&format=geojson&polygon_geojson=1&addressdetails=1`; const response = await fetch(request); const geojson = await response.json(); for (const feature of geojson.features) { const center = [ feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2, feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2 ]; const point = { type: 'Feature', geometry: { type: 'Point', coordinates: center }, place_name: feature.properties.display_name, properties: feature.properties, text: feature.properties.display_name, place_type: ['place'], center }; features.push(point); } } catch (e) { console.error(`Failed to forwardGeocode with error: ${e}`); // eslint-disable-line } return { features }; } }; /* eslint-disable complexity,max-statements */ export default function GeocoderControl(props: GeocoderControlProps) { const [marker, setMarker] = useState(null); const geocoder = useControl( ({mapLib}) => { const ctrl = new MaplibreGeocoder(geocoderApi, { ...props, marker: false, maplibregl: mapLib }); ctrl.on('loading', props.onLoading); ctrl.on('results', props.onResults); ctrl.on('result', evt => { props.onResult(evt); const {result} = evt; const location = result && (result.center || (result.geometry?.type === 'Point' && result.geometry.coordinates)); if (location && props.marker) { const markerProps = typeof props.marker === 'object' ? props.marker : {}; setMarker(); } else { setMarker(null); } }); ctrl.on('error', props.onError); return ctrl; }, { position: props.position } ); // @ts-ignore (TS2339) private member if (geocoder._map) { if (geocoder.getProximity() !== props.proximity && props.proximity !== undefined) { geocoder.setProximity(props.proximity); } if (geocoder.getRenderFunction() !== props.render && props.render !== undefined) { geocoder.setRenderFunction(props.render); } if (geocoder.getLanguage() !== props.language && props.language !== undefined) { geocoder.setLanguage(props.language); } if (geocoder.getZoom() !== props.zoom && props.zoom !== undefined) { geocoder.setZoom(props.zoom); } if (geocoder.getFlyTo() !== props.flyTo && props.flyTo !== undefined) { geocoder.setFlyTo(props.flyTo); } if (geocoder.getPlaceholder() !== props.placeholder && props.placeholder !== undefined) { geocoder.setPlaceholder(props.placeholder); } if (geocoder.getCountries() !== props.countries && props.countries !== undefined) { geocoder.setCountries(props.countries); } if (geocoder.getTypes() !== props.types && props.types !== undefined) { geocoder.setTypes(props.types); } if (geocoder.getMinLength() !== props.minLength && props.minLength !== undefined) { geocoder.setMinLength(props.minLength); } if (geocoder.getLimit() !== props.limit && props.limit !== undefined) { geocoder.setLimit(props.limit); } if (geocoder.getFilter() !== props.filter && props.filter !== undefined) { geocoder.setFilter(props.filter); } // if (geocoder.getOrigin() !== props.origin && props.origin !== undefined) { // geocoder.setOrigin(props.origin); // } // if (geocoder.getAutocomplete() !== props.autocomplete && props.autocomplete !== undefined) { // geocoder.setAutocomplete(props.autocomplete); // } // if (geocoder.getFuzzyMatch() !== props.fuzzyMatch && props.fuzzyMatch !== undefined) { // geocoder.setFuzzyMatch(props.fuzzyMatch); // } // if (geocoder.getRouting() !== props.routing && props.routing !== undefined) { // geocoder.setRouting(props.routing); // } // if (geocoder.getWorldview() !== props.worldview && props.worldview !== undefined) { // geocoder.setWorldview(props.worldview); // } } return marker; } const noop = () => {}; GeocoderControl.defaultProps = { marker: true, onLoading: noop, onResults: noop, onResult: noop, onError: noop }; ================================================ FILE: examples/maplibre/geocoder/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/geojson/README.md ================================================ # Example: GeoJSON This example showcases how to dynamically add and update custom data sources. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/geojson/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/geojson/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "d3-array": "^3.1.1", "d3-scale": "^4.0.2", "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/geojson/src/app.tsx ================================================ import * as React from 'react'; import {useState, useEffect, useMemo, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import {dataLayer} from './map-style'; import {updatePercentiles} from './utils'; export default function App() { const [year, setYear] = useState(2015); const [allData, setAllData] = useState(null); const [hoverInfo, setHoverInfo] = useState(null); useEffect(() => { /* global fetch */ fetch( 'https://raw.githubusercontent.com/uber/react-map-gl/master/examples/.data/us-income.geojson' ) .then(resp => resp.json()) .then(json => setAllData(json)) .catch(err => console.error('Could not load data', err)); // eslint-disable-line }, []); const onHover = useCallback(event => { const { features, point: {x, y} } = event; const hoveredFeature = features && features[0]; // prettier-ignore setHoverInfo(hoveredFeature && {feature: hoveredFeature, x, y}); }, []); const data = useMemo(() => { return allData && updatePercentiles(allData, f => f.properties.income[year]); }, [allData, year]); return ( <> {hoverInfo && (
State: {hoverInfo.feature.properties.name}
Median Household Income: {hoverInfo.feature.properties.value}
Percentile: {(hoverInfo.feature.properties.percentile / 8) * 100}
)}
setYear(value)} /> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/geojson/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel(props) { const {year} = props; return (

Interactive GeoJSON

Map showing median household income by state in year {year}. Hover over a state to see details.

Data source: US Census Bureau


props.onChange(evt.target.value)} />
); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/geojson/src/map-style.ts ================================================ import type {LayerProps} from 'react-map-gl/maplibre'; // For more information on data-driven styles, see https://maplibre.org/maplibre-style-spec/expressions/ export const dataLayer: LayerProps = { id: 'data', type: 'fill', paint: { 'fill-color': { type: 'interval', property: 'percentile', stops: [ [0, '#3288bd'], [1, '#66c2a5'], [2, '#abdda4'], [3, '#e6f598'], [4, '#ffffbf'], [5, '#fee08b'], [6, '#fdae61'], [7, '#f46d43'], [8, '#d53e4f'] ] }, 'fill-opacity': 0.8 } }; ================================================ FILE: examples/maplibre/geojson/src/utils.ts ================================================ import {range} from 'd3-array'; import {scaleQuantile} from 'd3-scale'; import type GeoJSON from 'geojson'; export function updatePercentiles( featureCollection: GeoJSON.FeatureCollection, accessor: (f: GeoJSON.Feature) => number ): GeoJSON.FeatureCollection { const {features} = featureCollection; const scale = scaleQuantile().domain(features.map(accessor)).range(range(9)); return { type: 'FeatureCollection', features: features.map(f => { const value = accessor(f); const properties = { ...f.properties, value, percentile: scale(value) }; return {...f, properties}; }) }; } ================================================ FILE: examples/maplibre/geojson/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/geojson-animation/README.md ================================================ # Example: Animated GeoJSON This app reproduces Maplibre's [Animate point along line](https://maplibre.org/maplibre-gl-js/docs/examples/animate-point-along-line/) example. This example showcases how to dynamically add and update custom data sources. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/geojson-animation/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/geojson-animation/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/geojson-animation/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useEffect} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from 'react-map-gl/maplibre'; import type {LayerProps} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; const pointLayer: LayerProps = { id: 'point', type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; function pointOnCircle({center, angle, radius}) { return { type: 'Point', coordinates: [center[0] + Math.cos(angle) * radius, center[1] + Math.sin(angle) * radius] }; } export default function App() { const [pointData, setPointData] = useState(null); useEffect(() => { const animation = window.requestAnimationFrame(() => setPointData(pointOnCircle({center: [-100, 0], angle: Date.now() / 1000, radius: 20})) ); return () => window.cancelAnimationFrame(animation); }); return ( <> {pointData && ( )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/geojson-animation/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Animated GeoJSON

Render animation by updating GeoJSON data source.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/geojson-animation/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/globe/README.md ================================================ # Example: Globe This app reproduces Maplibre's [globe](https://maplibre.org/maplibre-gl-js/docs/examples/globe/) example. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/globe/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/globe/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0-pre.1", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/globe/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; export default function App() { return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/globe/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Globe

Use globe projection.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/globe/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/heatmap/README.md ================================================ # Example: Heatmap layer This app reproduces Maplibre's [Create a heatmap layer](https://maplibre.org/maplibre-gl-js/docs/examples/heatmap-layer/) example. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/heatmap/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/heatmap/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/heatmap/src/app.tsx ================================================ import * as React from 'react'; import {useState, useEffect, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import MapGL, {Source, Layer} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import {heatmapLayer} from './map-style'; function filterFeaturesByDay(featureCollection, time) { const date = new Date(time); const year = date.getFullYear(); const month = date.getMonth(); const day = date.getDate(); const features = featureCollection.features.filter(feature => { const featureDate = new Date(feature.properties.time); return ( featureDate.getFullYear() === year && featureDate.getMonth() === month && featureDate.getDate() === day ); }); return {type: 'FeatureCollection', features}; } export default function App() { const [allDays, useAllDays] = useState(true); const [timeRange, setTimeRange] = useState([0, 0]); const [selectedTime, selectTime] = useState(0); const [earthquakes, setEarthQuakes] = useState(null); useEffect(() => { /* global fetch */ fetch('https://maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson') .then(resp => resp.json()) .then(json => { // Note: In a real application you would do a validation of JSON data before doing anything with it, // but for demonstration purposes we ingore this part here and just trying to select needed data... const features = json.features; const endTime = features[0].properties.time; const startTime = features[features.length - 1].properties.time; setTimeRange([startTime, endTime]); setEarthQuakes(json); selectTime(endTime); }) .catch(err => console.error('Could not load data', err)); // eslint-disable-line }, []); const data = useMemo(() => { return allDays ? earthquakes : filterFeaturesByDay(earthquakes, selectedTime); }, [earthquakes, allDays, selectedTime]); return ( <> {data && ( )} ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/heatmap/src/control-panel.tsx ================================================ import * as React from 'react'; function formatTime(time) { const date = new Date(time); return `${date.getMonth() + 1}/${date.getDate()}/${date.getFullYear()}`; } function ControlPanel(props) { const {startTime, endTime, onChangeTime, allDays, onChangeAllDays, selectedTime} = props; const day = 24 * 60 * 60 * 1000; const days = Math.round((endTime - startTime) / day); const selectedDay = Math.round((selectedTime - startTime) / day); const onSelectDay = evt => { const daysToAdd = evt.target.value; // add selected days to start time to calculate new time const newTime = startTime + daysToAdd * day; onChangeTime(newTime); }; return (

Heatmap

Map showing earthquakes
from {formatTime(startTime)} to {formatTime(endTime)}.


onChangeAllDays(evt.target.checked)} />

Data source:{' '} earthquakes.geojson

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/heatmap/src/map-style.ts ================================================ import type {LayerProps} from 'react-map-gl/maplibre'; const MAX_ZOOM_LEVEL = 9; export const heatmapLayer: LayerProps = { id: 'heatmap', maxzoom: MAX_ZOOM_LEVEL, type: 'heatmap', paint: { // Increase the heatmap weight based on frequency and property magnitude 'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1], // Increase the heatmap color weight weight by zoom level // heatmap-intensity is a multiplier on top of heatmap-weight 'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, MAX_ZOOM_LEVEL, 3], // Color ramp for heatmap. Domain is 0 (low) to 1 (high). // Begin color ramp at 0-stop with a 0-transparancy color // to create a blur-like effect. 'heatmap-color': [ 'interpolate', ['linear'], ['heatmap-density'], 0, 'rgba(33,102,172,0)', 0.2, 'rgb(103,169,207)', 0.4, 'rgb(209,229,240)', 0.6, 'rgb(253,219,199)', 0.8, 'rgb(239,138,98)', 0.9, 'rgb(255,201,101)' ], // Adjust the heatmap radius by zoom level 'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, MAX_ZOOM_LEVEL, 20], // Transition from heatmap to circle layer by zoom level 'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0] } }; ================================================ FILE: examples/maplibre/heatmap/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/interaction/README.md ================================================ # Example: Interaction This example showcases how to toggle/limit user interaction. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/interaction/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/interaction/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/interaction/src/app.tsx ================================================ import * as React from 'react'; import {useState, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; const initialViewState = { latitude: 37.729, longitude: -122.36, zoom: 11, bearing: 0, pitch: 50 }; export default function App() { const [settings, setSettings] = useState({ scrollZoom: true, boxZoom: true, dragRotate: true, dragPan: true, keyboard: true, doubleClickZoom: true, touchZoomRotate: true, touchPitch: true, minZoom: 0, maxZoom: 20, minPitch: 0, maxPitch: 85 }); const updateSettings = useCallback( (name, value) => setSettings(s => ({ ...s, [name]: value })), [] ); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/interaction/src/control-panel.tsx ================================================ import * as React from 'react'; const camelPattern = /(^|[A-Z])[a-z]*/g; function formatSettingName(name) { return name.match(camelPattern).join(' '); } function Checkbox({name, value, onChange}) { return (
onChange(name, evt.target.checked)} />
); } function NumericInput({name, value, onChange}) { return (
onChange(name, Number(evt.target.value))} />
); } function ControlPanel(props) { const {settings, onChange} = props; const renderSetting = (name, value) => { switch (typeof value) { case 'boolean': return ; case 'number': return ; default: return null; } }; return (

Limit Map Interaction

Turn interactive features off/on.


{Object.keys(settings).map(name => renderSetting(name, settings[name]))}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/interaction/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/layers/README.md ================================================ # Example: Layers This example showcases how to dynamically change layer styles and show/hide layers. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/layers/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/layers/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "immutable": "^4.0.0", "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/layers/src/app.tsx ================================================ import * as React from 'react'; import {useState} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; export default function App() { const [mapStyle, setMapStyle] = useState(null); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/layers/src/control-panel.tsx ================================================ import * as React from 'react'; import {useState, useEffect} from 'react'; import {fromJS} from 'immutable'; import MAP_STYLE from '../../map-style-basic-v8.json'; const defaultMapStyle: any = fromJS(MAP_STYLE); const defaultLayers = defaultMapStyle.get('layers'); const categories = ['labels', 'roads', 'buildings', 'parks', 'water', 'background']; // Layer id patterns by category const layerSelector = { background: /background/, water: /water/, parks: /park/, buildings: /building/, roads: /bridge|road|tunnel/, labels: /label|place|poi/ }; // Layer color class by type const colorClass = { line: 'line-color', fill: 'fill-color', background: 'background-color', symbol: 'text-color' }; function getMapStyle({visibility, color}) { const layers = defaultLayers .filter(layer => { const id = layer.get('id'); return categories.every(name => visibility[name] || !layerSelector[name].test(id)); }) .map(layer => { const id = layer.get('id'); const type = layer.get('type'); const category = categories.find(name => layerSelector[name].test(id)); if (category && colorClass[type]) { return layer.setIn(['paint', colorClass[type]], color[category]); } return layer; }); return defaultMapStyle.set('layers', layers); } function StyleControls(props) { const [visibility, setVisibility] = useState({ water: true, parks: true, buildings: true, roads: true, labels: true, background: true }); const [color, setColor] = useState({ water: '#DBE2E6', parks: '#E6EAE9', buildings: '#c0c0c8', roads: '#ffffff', labels: '#78888a', background: '#EBF0F0' }); useEffect(() => { props.onChange(getMapStyle({visibility, color})); }, [visibility, color]); const onColorChange = (name, value) => { setColor({...color, [name]: value}); }; const onVisibilityChange = (name, value) => { setVisibility({...visibility, [name]: value}); }; return (

Dynamic Styling

Dynamically show/hide map layers and change color with Immutable map style.


{categories.map(name => (
onVisibilityChange(name, evt.target.checked)} /> onColorChange(name, evt.target.value)} />
))}
); } export default React.memo(StyleControls); ================================================ FILE: examples/maplibre/layers/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/map-style-basic-v8.json ================================================ { "version": 8, "name": "Positron", "metadata": {}, "sources": { "carto": { "type": "vector", "url": "https://tiles.basemaps.cartocdn.com/vector/carto.streets/v1/tiles.json" } }, "sprite": "https://tiles.basemaps.cartocdn.com/gl/positron-gl-style/sprite", "glyphs": "https://tiles.basemaps.cartocdn.com/fonts/{fontstack}/{range}.pbf", "layers": [ { "id": "background", "type": "background", "layout": { "visibility": "visible" }, "paint": { "background-color": "#fafaf8", "background-opacity": 1 } }, { "id": "landcover", "type": "fill", "source": "carto", "source-layer": "landcover", "filter": [ "any", [ "==", "class", "wood" ], [ "==", "class", "grass" ], [ "==", "subclass", "recreation_ground" ] ], "paint": { "fill-color": { "stops": [ [ 8, "rgba(234, 241, 233, 0.5)" ], [ 9, "rgba(234, 241, 233, 0.5)" ], [ 11, "rgba(234, 241, 233, 0.5)" ], [ 13, "rgba(234, 241, 233, 0.5)" ], [ 15, "rgba(234, 241, 233, 0.5)" ] ] }, "fill-opacity": 1 } }, { "id": "park_national_park", "type": "fill", "source": "carto", "source-layer": "park", "minzoom": 9, "filter": [ "all", [ "==", "class", "national_park" ] ], "layout": { "visibility": "visible" }, "paint": { "fill-color": { "stops": [ [ 8, "rgba(234, 241, 233, 0.5)" ], [ 9, "rgba(234, 241, 233, 0.5)" ], [ 11, "rgba(234, 241, 233, 0.5)" ], [ 13, "rgba(234, 241, 233, 0.5)" ], [ 15, "rgba(234, 241, 233, 0.5)" ] ] }, "fill-opacity": 1, "fill-translate-anchor": "map" } }, { "id": "park_nature_reserve", "type": "fill", "source": "carto", "source-layer": "park", "minzoom": 0, "filter": [ "all", [ "==", "class", "nature_reserve" ] ], "layout": { "visibility": "visible" }, "paint": { "fill-color": { "stops": [ [ 8, "rgba(234, 241, 233, 0.5)" ], [ 9, "rgba(234, 241, 233, 0.5)" ], [ 11, "rgba(234, 241, 233, 0.5)" ], [ 13, "rgba(234, 241, 233, 0.5)" ], [ 15, "rgba(234, 241, 233, 0.5)" ] ] }, "fill-antialias": true, "fill-opacity": { "stops": [ [ 6, 0.7 ], [ 9, 0.9 ] ] } } }, { "id": "landuse_residential", "type": "fill", "source": "carto", "source-layer": "landuse", "minzoom": 6, "filter": [ "any", [ "==", "class", "residential" ] ], "paint": { "fill-color": { "stops": [ [ 5, "rgba(237, 237, 237, 0.5)" ], [ 8, "rgba(237, 237, 237, 0.45)" ], [ 9, "rgba(237, 237, 237, 0.4)" ], [ 11, "rgba(237, 237, 237, 0.35)" ], [ 13, "rgba(237, 237, 237, 0.3)" ], [ 15, "rgba(237, 237, 237, 0.25)" ], [ 16, "rgba(237, 237, 237, 0.25)" ] ] }, "fill-opacity": { "stops": [ [ 6, 0.6 ], [ 9, 1 ] ] } } }, { "id": "landuse", "type": "fill", "source": "carto", "source-layer": "landuse", "filter": [ "any", [ "==", "class", "cemetery" ], [ "==", "class", "stadium" ] ], "paint": { "fill-color": { "stops": [ [ 8, "rgba(234, 241, 233, 0.5)" ], [ 9, "rgba(234, 241, 233, 0.5)" ], [ 11, "rgba(234, 241, 233, 0.5)" ], [ 13, "rgba(234, 241, 233, 0.5)" ], [ 15, "rgba(234, 241, 233, 0.5)" ] ] } } }, { "id": "waterway", "type": "line", "source": "carto", "source-layer": "waterway", "paint": { "line-color": "#d1dbdf", "line-width": { "stops": [ [ 8, 0.5 ], [ 9, 1 ], [ 15, 2 ], [ 16, 3 ] ] } } }, { "id": "boundary_county", "type": "line", "source": "carto", "source-layer": "boundary", "minzoom": 9, "maxzoom": 24, "filter": [ "all", [ "==", "admin_level", 6 ], [ "==", "maritime", 0 ] ], "paint": { "line-color": { "stops": [ [ 4, "#ead5d7" ], [ 5, "#ead5d7" ], [ 6, "#e1c5c7" ] ] }, "line-width": { "stops": [ [ 4, 0.5 ], [ 7, 1 ] ] }, "line-dasharray": { "stops": [ [ 6, [ 1 ] ], [ 7, [ 2, 2 ] ] ] } } }, { "id": "boundary_state", "type": "line", "source": "carto", "source-layer": "boundary", "minzoom": 4, "filter": [ "all", [ "==", "admin_level", 4 ], [ "==", "maritime", 0 ] ], "paint": { "line-color": { "stops": [ [ 4, "#ead5d7" ], [ 5, "#ead5d7" ], [ 6, "#e1c5c7" ] ] }, "line-width": { "stops": [ [ 4, 0.5 ], [ 7, 1 ], [ 8, 1 ], [ 9, 1.2 ] ] }, "line-dasharray": { "stops": [ [ 6, [ 1 ] ], [ 7, [ 2, 2 ] ] ] } } }, { "id": "water", "type": "fill", "source": "carto", "source-layer": "water", "minzoom": 0, "maxzoom": 24, "filter": [ "all", [ "==", "$type", "Polygon" ] ], "layout": { "visibility": "visible" }, "paint": { "fill-color": "#d4dadc", "fill-antialias": true, "fill-translate-anchor": "map", "fill-opacity": 1 } }, { "id": "water_shadow", "type": "fill", "source": "carto", "source-layer": "water", "minzoom": 0, "filter": [ "all", [ "==", "$type", "Polygon" ] ], "layout": { "visibility": "visible" }, "paint": { "fill-color": "transparent", "fill-antialias": true, "fill-translate-anchor": "map", "fill-opacity": 1, "fill-translate": { "stops": [ [ 0, [ 0, 2 ] ], [ 6, [ 0, 1 ] ], [ 14, [ 0, 1 ] ], [ 17, [ 0, 2 ] ] ] } } }, { "id": "aeroway-runway", "type": "line", "source": "carto", "source-layer": "aeroway", "minzoom": 12, "filter": [ "all", [ "==", "class", "runway" ] ], "layout": { "line-cap": "square" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ] ] }, "line-color": "#e8e8e8" } }, { "id": "aeroway-taxiway", "type": "line", "source": "carto", "source-layer": "aeroway", "minzoom": 13, "filter": [ "all", [ "==", "class", "taxiway" ] ], "paint": { "line-color": "#e8e8e8", "line-width": { "stops": [ [ 13, 0.5 ], [ 14, 1 ], [ 15, 2 ], [ 16, 4 ] ] } } }, { "id": "waterway_label", "type": "symbol", "source": "carto", "source-layer": "waterway", "filter": [ "all", [ "has", "name" ], [ "==", "class", "river" ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Regular Italic", "Open Sans Italic", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "symbol-placement": "line", "symbol-spacing": 300, "symbol-avoid-edges": false, "text-size": { "stops": [ [ 9, 8 ], [ 10, 9 ] ] }, "text-padding": 2, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-offset": { "stops": [ [ 6, [ 0, -0.2 ] ], [ 11, [ 0, -0.4 ] ], [ 12, [ 0, -0.6 ] ] ] }, "text-letter-spacing": 0, "text-keep-upright": true }, "paint": { "text-color": "#7a96a0", "text-halo-color": "#f5f5f3", "text-halo-width": 1 } }, { "id": "tunnel_service_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 1 ], [ 16, 3 ], [ 17, 6 ], [ 18, 8 ] ] }, "line-opacity": 1, "line-color": "#ddd" } }, { "id": "tunnel_minor_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "miter" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 0.5 ], [ 14, 2 ], [ 15, 4 ], [ 16, 6 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-color": "#ddd" } }, { "id": "tunnel_sec_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 1 ], [ 13, 2 ], [ 14, 5 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#ddd" } }, { "id": "tunnel_pri_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 8, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": "#ddd" } }, { "id": "tunnel_trunk_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round", "visibility": "visible" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": "#ddd" } }, { "id": "tunnel_mot_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 12, 4 ], [ 13, 5 ], [ 14, 7 ], [ 15, 9 ], [ 16, 11 ], [ 17, 13 ], [ 18, 22 ] ] }, "line-opacity": { "stops": [ [ 6, 0.5 ], [ 7, 1 ] ] }, "line-color": "#ddd" } }, { "id": "tunnel_path", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "path" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 0.5 ], [ 16, 1 ], [ 18, 3 ] ] }, "line-opacity": 1, "line-color": "#d5d5d5", "line-dasharray": { "stops": [ [ 15, [ 2, 2 ] ], [ 18, [ 3, 3 ] ] ] } } }, { "id": "tunnel_service_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 2 ], [ 16, 2 ], [ 17, 4 ], [ 18, 6 ] ] }, "line-opacity": 1, "line-color": "#eee" } }, { "id": "tunnel_minor_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 3 ], [ 16, 4 ], [ 17, 8 ], [ 18, 12 ] ] }, "line-opacity": 1, "line-color": "rgba(238, 238, 238, 1)" } }, { "id": "tunnel_sec_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 4 ], [ 16, 6 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-color": "#eee" } }, { "id": "tunnel_pri_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#eee" } }, { "id": "tunnel_trunk_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "round", "line-join": "round", "visibility": "visible" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#eee" } }, { "id": "tunnel_mot_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 10, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "tunnel" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 10, 1 ], [ 12, 2 ], [ 13, 3 ], [ 14, 5 ], [ 15, 7 ], [ 16, 9 ], [ 17, 11 ], [ 18, 20 ] ] }, "line-opacity": 1, "line-color": "#eee" } }, { "id": "tunnel_rail", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "filter": [ "all", [ "==", "class", "rail" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "visibility": "visible", "line-join": "round" }, "paint": { "line-color": "#dddddd", "line-width": { "base": 1.3, "stops": [ [ 13, 0.5 ], [ 14, 1 ], [ 15, 1 ], [ 16, 3 ], [ 21, 7 ] ] }, "line-opacity": 0.5 } }, { "id": "tunnel_rail_dash", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "filter": [ "all", [ "==", "class", "rail" ], [ "==", "brunnel", "tunnel" ] ], "layout": { "visibility": "visible", "line-join": "round" }, "paint": { "line-color": "#ffffff", "line-width": { "base": 1.3, "stops": [ [ 15, 0.5 ], [ 16, 1 ], [ 20, 5 ] ] }, "line-dasharray": { "stops": [ [ 15, [ 5, 5 ] ], [ 16, [ 6, 6 ] ] ] }, "line-opacity": 0.5 } }, { "id": "road_service_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 1 ], [ 16, 3 ], [ 17, 6 ], [ 18, 8 ] ] }, "line-opacity": 1, "line-color": "#ddd" } }, { "id": "road_minor_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 0.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 4.3 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-opacity": 1, "line-color": { "stops": [ [ 13, "#e6e6e6" ], [ 15.7, "#e6e6e6" ], [ 16, "#ddd" ] ] } } }, { "id": "road_pri_case_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 2 ], [ 13, 3 ], [ 14, 4 ], [ 15, 5 ], [ 16, 8 ], [ 17, 10 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": "#ddd" } }, { "id": "road_trunk_case_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 2 ], [ 13, 3 ], [ 14, 4 ], [ 15, 5 ], [ 16, 8 ], [ 17, 10 ] ] }, "line-opacity": 1, "line-color": { "stops": [ [ 12, "#e6e6e6" ], [ 14, "#ddd" ] ] } } }, { "id": "road_mot_case_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 2 ], [ 13, 3 ], [ 14, 4 ], [ 15, 5 ], [ 16, 8 ], [ 17, 10 ] ] }, "line-opacity": 1, "line-color": { "stops": [ [ 12, "#e6e6e6" ], [ 14, "#ddd" ] ] } } }, { "id": "road_sec_case_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 1.5 ], [ 13, 3 ], [ 14, 5 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": { "stops": [ [ 11, "#e6e6e6" ], [ 12.99, "#e6e6e6" ], [ 13, "#ddd" ] ] } } }, { "id": "road_pri_case_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 7, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 7, "#e6e6e6" ], [ 12, "#ddd" ] ] } } }, { "id": "road_trunk_case_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 5, "#e6e6e6" ], [ 12, "#ddd" ] ] } } }, { "id": "road_mot_case_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.7 ], [ 8, 0.8 ], [ 11, 3 ], [ 12, 4 ], [ 13, 5 ], [ 14, 7 ], [ 15, 9 ], [ 16, 11 ], [ 17, 13 ], [ 18, 22 ] ] }, "line-opacity": { "stops": [ [ 6, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 5, "#e6e6e6" ], [ 12, "#ddd" ] ] } } }, { "id": "road_path", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "in", "class", "path", "track" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 0.5 ], [ 16, 1 ], [ 18, 3 ] ] }, "line-opacity": 1, "line-color": "#d5d5d5", "line-dasharray": { "stops": [ [ 15, [ 2, 2 ] ], [ 18, [ 3, 3 ] ] ] } } }, { "id": "road_service_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 2 ], [ 16, 2 ], [ 17, 4 ], [ 18, 6 ] ] }, "line-opacity": 1, "line-color": "#fdfdfd" } }, { "id": "road_minor_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 3 ], [ 16, 4 ], [ 17, 8 ], [ 18, 12 ] ] }, "line-opacity": 1, "line-color": "#fdfdfd" } }, { "id": "road_pri_fill_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 1 ], [ 13, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 6 ], [ 17, 8 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_trunk_fill_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "square", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 1 ], [ 13, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 6 ], [ 17, 8 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_mot_fill_ramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 12, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "==", "ramp", 1 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 12, 1 ], [ 13, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 6 ], [ 17, 8 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_sec_fill_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 4 ], [ 16, 6 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_pri_fill_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 10, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 10, 0.3 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_trunk_fill_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 10, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "road_mot_fill_noramp", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 10, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "!has", "brunnel" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 10, 1 ], [ 12, 2 ], [ 13, 3 ], [ 14, 5 ], [ 15, 7 ], [ 16, 9 ], [ 17, 11 ], [ 18, 20 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "rail", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "filter": [ "all", [ "==", "class", "rail" ], [ "!=", "brunnel", "tunnel" ] ], "layout": { "visibility": "visible", "line-join": "round" }, "paint": { "line-color": "#dddddd", "line-width": { "base": 1.3, "stops": [ [ 13, 0.5 ], [ 14, 1 ], [ 15, 1 ], [ 16, 3 ], [ 21, 7 ] ] } } }, { "id": "rail_dash", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "filter": [ "all", [ "==", "class", "rail" ], [ "!=", "brunnel", "tunnel" ] ], "layout": { "visibility": "visible", "line-join": "round" }, "paint": { "line-color": "#ffffff", "line-width": { "base": 1.3, "stops": [ [ 15, 0.5 ], [ 16, 1 ], [ 20, 5 ] ] }, "line-dasharray": { "stops": [ [ 15, [ 5, 5 ] ], [ 16, [ 6, 6 ] ] ] } } }, { "id": "bridge_service_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 1 ], [ 16, 3 ], [ 17, 6 ], [ 18, 8 ] ] }, "line-opacity": 1, "line-color": "#ddd" } }, { "id": "bridge_minor_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "miter" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 0.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 4.3 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-opacity": 1, "line-color": { "stops": [ [ 13, "#e6e6e6" ], [ 15.7, "#e6e6e6" ], [ 16, "#ddd" ] ] } } }, { "id": "bridge_sec_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "miter" }, "paint": { "line-width": { "stops": [ [ 11, 0.5 ], [ 12, 1.5 ], [ 13, 3 ], [ 14, 5 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": { "stops": [ [ 11, "#e6e6e6" ], [ 12.99, "#e6e6e6" ], [ 13, "#ddd" ] ] } } }, { "id": "bridge_pri_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 8, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 8, "#e6e6e6" ], [ 12, "#ddd" ] ] } } }, { "id": "bridge_trunk_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round", "visibility": "visible" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 13, 4 ], [ 14, 6 ], [ 15, 8 ], [ 16, 10 ], [ 17, 14 ], [ 18, 18 ] ] }, "line-opacity": { "stops": [ [ 5, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 5, "#e6e6e6" ], [ 12, "#ddd" ] ] } } }, { "id": "bridge_mot_case", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 5, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 6, 0.5 ], [ 7, 0.8 ], [ 8, 1 ], [ 11, 3 ], [ 12, 4 ], [ 13, 5 ], [ 14, 7 ], [ 15, 9 ], [ 16, 11 ], [ 17, 13 ], [ 18, 22 ] ] }, "line-opacity": { "stops": [ [ 6, 0.5 ], [ 7, 1 ] ] }, "line-color": { "stops": [ [ 5, "#e6e6e6" ], [ 10, "#ddd" ] ] } } }, { "id": "bridge_path", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "path" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 0.5 ], [ 16, 1 ], [ 18, 3 ] ] }, "line-opacity": 1, "line-color": "#d5d5d5", "line-dasharray": { "stops": [ [ 15, [ 2, 2 ] ], [ 18, [ 3, 3 ] ] ] } } }, { "id": "bridge_service_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "service" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 2 ], [ 16, 2 ], [ 17, 4 ], [ 18, 6 ] ] }, "line-opacity": 1, "line-color": "#fdfdfd" } }, { "id": "bridge_minor_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 15, "maxzoom": 24, "filter": [ "all", [ "==", "class", "minor" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 15, 3 ], [ 16, 4 ], [ 17, 8 ], [ 18, 12 ] ] }, "line-opacity": 1, "line-color": "#fdfdfd" } }, { "id": "bridge_sec_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 13, "maxzoom": 24, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 4 ], [ 16, 6 ], [ 17, 10 ], [ 18, 14 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "bridge_pri_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "==", "class", "primary" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "bridge_trunk_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 11, "maxzoom": 24, "filter": [ "all", [ "==", "class", "trunk" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round", "visibility": "visible" }, "paint": { "line-width": { "stops": [ [ 11, 1 ], [ 13, 2 ], [ 14, 4 ], [ 15, 6 ], [ 16, 8 ], [ 17, 12 ], [ 18, 16 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "bridge_mot_fill", "type": "line", "source": "carto", "source-layer": "transportation", "minzoom": 10, "maxzoom": 24, "filter": [ "all", [ "==", "class", "motorway" ], [ "!=", "ramp", 1 ], [ "==", "brunnel", "bridge" ] ], "layout": { "line-cap": "butt", "line-join": "round" }, "paint": { "line-width": { "stops": [ [ 10, 1 ], [ 12, 2 ], [ 13, 3 ], [ 14, 5 ], [ 15, 7 ], [ 16, 9 ], [ 17, 11 ], [ 18, 20 ] ] }, "line-opacity": 1, "line-color": "#fff" } }, { "id": "building", "type": "fill", "source": "carto", "source-layer": "building", "layout": { "visibility": "visible" }, "paint": { "fill-color": { "base": 1, "stops": [ [ 15.5, "#dfdfdf" ], [ 16, "#dfdfdf" ] ] }, "fill-antialias": true } }, { "id": "building-top", "type": "fill", "source": "carto", "source-layer": "building", "layout": { "visibility": "visible" }, "paint": { "fill-translate": { "base": 1, "stops": [ [ 14, [ 0, 0 ] ], [ 16, [ -2, -2 ] ] ] }, "fill-outline-color": "#dfdfdf", "fill-color": "#ededed", "fill-opacity": { "base": 1, "stops": [ [ 13, 0 ], [ 16, 1 ] ] } } }, { "id": "boundary_country_outline", "type": "line", "source": "carto", "source-layer": "boundary", "minzoom": 6, "maxzoom": 24, "filter": [ "all", [ "==", "admin_level", 2 ], [ "==", "maritime", 0 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#f3efed", "line-opacity": 0.5, "line-width": 8, "line-offset": 0 } }, { "id": "boundary_country_inner", "type": "line", "source": "carto", "source-layer": "boundary", "minzoom": 0, "filter": [ "all", [ "==", "admin_level", 2 ], [ "==", "maritime", 0 ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 4, "#f2e6e7" ], [ 5, "#ebd6d8" ], [ 6, "#ebd6d8" ] ] }, "line-opacity": 1, "line-width": { "stops": [ [ 3, 1 ], [ 6, 1.5 ] ] }, "line-offset": 0 } }, { "id": "watername_ocean", "type": "symbol", "source": "carto", "source-layer": "water_name", "minzoom": 0, "maxzoom": 5, "filter": [ "all", [ "has", "name" ], [ "==", "$type", "Point" ], [ "==", "class", "ocean" ] ], "layout": { "text-field": "{name}", "symbol-placement": "point", "text-size": { "stops": [ [ 0, 13 ], [ 2, 14 ], [ 4, 18 ] ] }, "text-font": [ "Montserrat Medium Italic", "Open Sans Italic", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-line-height": 1.2, "text-padding": 2, "text-allow-overlap": false, "text-ignore-placement": false, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-max-width": 6, "text-letter-spacing": 0.1 }, "paint": { "text-color": "#abb6be", "text-halo-color": "#d4dadc", "text-halo-width": 1, "text-halo-blur": 0 } }, { "id": "watername_sea", "type": "symbol", "source": "carto", "source-layer": "water_name", "minzoom": 5, "filter": [ "all", [ "has", "name" ], [ "==", "$type", "Point" ], [ "==", "class", "sea" ] ], "layout": { "text-field": "{name}", "symbol-placement": "point", "text-size": 12, "text-font": [ "Montserrat Medium Italic", "Open Sans Italic", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-line-height": 1.2, "text-padding": 2, "text-allow-overlap": false, "text-ignore-placement": false, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-max-width": 6, "text-letter-spacing": 0.1 }, "paint": { "text-color": "#abb6be", "text-halo-color": "#d4dadc", "text-halo-width": 1, "text-halo-blur": 0 } }, { "id": "watername_lake", "type": "symbol", "source": "carto", "source-layer": "water_name", "minzoom": 4, "filter": [ "all", [ "has", "name" ], [ "==", "$type", "Point" ], [ "==", "class", "lake" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "symbol-placement": "point", "text-size": { "stops": [ [ 13, 9 ], [ 14, 10 ], [ 15, 11 ], [ 16, 12 ], [ 17, 13 ] ] }, "text-font": [ "Montserrat Regular Italic", "Open Sans Italic", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-line-height": 1.2, "text-padding": 2, "text-allow-overlap": false, "text-ignore-placement": false, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto" }, "paint": { "text-color": "#7a96a0", "text-halo-color": "#f5f5f3", "text-halo-width": 1, "text-halo-blur": 1 } }, { "id": "watername_lake_line", "type": "symbol", "source": "carto", "source-layer": "water_name", "filter": [ "all", [ "has", "name" ], [ "==", "$type", "LineString" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "symbol-placement": "line", "text-size": { "stops": [ [ 13, 9 ], [ 14, 10 ], [ 15, 11 ], [ 16, 12 ], [ 17, 13 ] ] }, "text-font": [ "Montserrat Regular Italic", "Open Sans Italic", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "symbol-spacing": 350, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-line-height": 1.2 }, "paint": { "text-color": "#7a96a0", "text-halo-color": "#f5f5f3", "text-halo-width": 1, "text-halo-blur": 1 } }, { "id": "place_hamlet", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 12, "maxzoom": 16, "filter": [ "any", [ "==", "class", "neighbourhood" ], [ "==", "class", "hamlet" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 14, "{name}" ] ] }, "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 13, 8 ], [ 14, 10 ], [ 16, 11 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": { "stops": [ [ 12, "none" ], [ 14, "uppercase" ] ] } }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_suburbs", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 12, "maxzoom": 16, "filter": [ "all", [ "==", "class", "suburb" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 12, 9 ], [ 13, 10 ], [ 14, 11 ], [ 15, 12 ], [ 16, 13 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": { "stops": [ [ 8, "none" ], [ 12, "uppercase" ] ] } }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_villages", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 10, "maxzoom": 16, "filter": [ "all", [ "==", "class", "village" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 10, 9 ], [ 12, 10 ], [ 13, 11 ], [ 14, 12 ], [ 16, 13 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": "none" }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_town", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 8, "maxzoom": 14, "filter": [ "all", [ "==", "class", "town" ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 8, 10 ], [ 9, 10 ], [ 10, 11 ], [ 13, 14 ], [ 14, 15 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": "none" }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_country_2", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 3, "maxzoom": 10, "filter": [ "all", [ "==", "class", "country" ], [ ">=", "rank", 3 ], [ "has", "iso_a2" ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 3, 10 ], [ 5, 11 ], [ 6, 12 ], [ 7, 13 ], [ 8, 14 ] ] }, "text-transform": "uppercase" }, "paint": { "text-color": { "stops": [ [ 3, "#8a99a4" ], [ 5, "#a1adb6" ], [ 6, "#b9c2c9" ] ] }, "text-halo-color": "#fafaf8", "text-halo-width": 1 } }, { "id": "place_country_1", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 2, "maxzoom": 7, "filter": [ "all", [ "==", "class", "country" ], [ "<=", "rank", 2 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 3, 11 ], [ 4, 12 ], [ 5, 13 ], [ 6, 14 ] ] }, "text-transform": "uppercase", "text-max-width": { "stops": [ [ 2, 6 ], [ 3, 6 ], [ 4, 9 ], [ 5, 12 ] ] } }, "paint": { "text-color": { "stops": [ [ 3, "#8a99a4" ], [ 5, "#a1adb6" ], [ 6, "#b9c2c9" ] ] }, "text-halo-color": "#fafaf8", "text-halo-width": 1 } }, { "id": "place_state", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 5, "maxzoom": 10, "filter": [ "all", [ "==", "class", "state" ], [ "<=", "rank", 4 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 5, 12 ], [ 7, 14 ] ] }, "text-transform": "uppercase", "text-max-width": 9 }, "paint": { "text-color": "#97a4ae", "text-halo-color": "#fafaf8", "text-halo-width": 0 } }, { "id": "place_continent", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 0, "maxzoom": 2, "filter": [ "all", [ "==", "class", "continent" ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-transform": "uppercase", "text-size": 14, "text-letter-spacing": 0.1, "text-max-width": 9, "text-justify": "center", "text-keep-upright": false }, "paint": { "text-color": "#697b89", "text-halo-color": "#fafaf8", "text-halo-width": 1 } }, { "id": "place_city_r6", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 8, "maxzoom": 15, "filter": [ "all", [ "==", "class", "city" ], [ ">=", "rank", 6 ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 8, 12 ], [ 9, 13 ], [ 10, 14 ], [ 13, 17 ], [ 14, 20 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": "uppercase" }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_city_r5", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 8, "maxzoom": 15, "filter": [ "all", [ "==", "class", "city" ], [ ">=", "rank", 0 ], [ "<=", "rank", 5 ] ], "layout": { "text-field": { "stops": [ [ 8, "{name_en}" ], [ 13, "{name}" ] ] }, "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 8, 14 ], [ 10, 16 ], [ 13, 19 ], [ 14, 22 ] ] }, "icon-image": "", "icon-offset": [ 16, 0 ], "text-anchor": "center", "icon-size": 1, "text-max-width": 10, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": "uppercase" }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_city_dot_r7", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 6, "maxzoom": 7, "filter": [ "all", [ "==", "class", "city" ], [ "<=", "rank", 7 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 12, "icon-image": "circle-11", "icon-offset": [ 16, 5 ], "text-anchor": "right", "icon-size": 0.4, "text-max-width": 8, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ] }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_city_dot_r4", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 5, "maxzoom": 7, "filter": [ "all", [ "==", "class", "city" ], [ "<=", "rank", 4 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 12, "icon-image": "circle-11", "icon-offset": [ 16, 5 ], "text-anchor": "right", "icon-size": 0.4, "text-max-width": 8, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ] }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_city_dot_r2", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 4, "maxzoom": 7, "filter": [ "all", [ "==", "class", "city" ], [ "<=", "rank", 2 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 12, "icon-image": "circle-11", "icon-offset": [ 16, 5 ], "text-anchor": "right", "icon-size": 0.4, "text-max-width": 8, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ] }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_city_dot_z7", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 7, "maxzoom": 8, "filter": [ "all", [ "!has", "capital" ], [ "!in", "class", "country", "state" ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 12, "icon-image": "circle-11", "icon-offset": [ 16, 5 ], "text-anchor": "right", "icon-size": 0.4, "text-max-width": 8, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ] }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "place_capital_dot_z7", "type": "symbol", "source": "carto", "source-layer": "place", "minzoom": 7, "maxzoom": 8, "filter": [ "all", [ ">", "capital", 0 ] ], "layout": { "text-field": "{name_en}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 12, "icon-image": "circle-11", "icon-offset": [ 16, 5 ], "text-anchor": "right", "icon-size": 0.4, "text-max-width": 8, "text-keep-upright": true, "text-offset": [ 0.2, 0.2 ], "text-transform": "uppercase" }, "paint": { "text-color": "#697b89", "icon-color": "#697b89", "icon-translate-anchor": "map", "text-halo-color": "rgba(255,255,255,0.5)", "text-halo-width": 1 } }, { "id": "poi_stadium", "type": "symbol", "source": "carto", "source-layer": "poi", "minzoom": 15, "filter": [ "all", [ "in", "class", "stadium", "cemetery", "attraction" ], [ "<=", "rank", 3 ] ], "layout": { "text-field": "{name}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 15, 8 ], [ 17, 9 ], [ 18, 10 ] ] }, "text-transform": "uppercase" }, "paint": { "text-color": "#7d9c83", "text-halo-color": "#f5f5f3", "text-halo-width": 1 } }, { "id": "poi_park", "type": "symbol", "source": "carto", "source-layer": "poi", "minzoom": 15, "filter": [ "all", [ "==", "class", "park" ] ], "layout": { "text-field": "{name}", "text-font": [ "Montserrat Medium", "Open Sans Bold", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 15, 8 ], [ 17, 9 ], [ 18, 10 ] ] }, "text-transform": "uppercase" }, "paint": { "text-color": "#7d9c83", "text-halo-color": "#f5f5f3", "text-halo-width": 1 } }, { "id": "roadname_minor", "type": "symbol", "source": "carto", "source-layer": "transportation_name", "minzoom": 16, "filter": [ "all", [ "in", "class", "minor", "service" ] ], "layout": { "symbol-placement": "line", "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": 9, "text-field": "{name}", "symbol-avoid-edges": false, "symbol-spacing": 200, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-justify": "center" }, "paint": { "text-color": "#838383", "text-halo-color": "#fff", "text-halo-width": 1 } }, { "id": "roadname_sec", "type": "symbol", "source": "carto", "source-layer": "transportation_name", "minzoom": 15, "filter": [ "all", [ "in", "class", "secondary", "tertiary" ] ], "layout": { "symbol-placement": "line", "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 15, 9 ], [ 16, 11 ], [ 18, 12 ] ] }, "text-field": "{name}", "symbol-avoid-edges": false, "symbol-spacing": 200, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-justify": "center" }, "paint": { "text-color": "#838383", "text-halo-color": "#fff", "text-halo-width": 1 } }, { "id": "roadname_pri", "type": "symbol", "source": "carto", "source-layer": "transportation_name", "minzoom": 14, "filter": [ "all", [ "in", "class", "primary" ] ], "layout": { "symbol-placement": "line", "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 14, 10 ], [ 15, 10 ], [ 16, 11 ], [ 18, 12 ] ] }, "text-field": "{name}", "symbol-avoid-edges": false, "symbol-spacing": { "stops": [ [ 6, 200 ], [ 16, 250 ] ] }, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-justify": "center", "text-letter-spacing": { "stops": [ [ 14, 0 ], [ 16, 0.2 ] ] } }, "paint": { "text-color": "#838383", "text-halo-color": "#fff", "text-halo-width": 1 } }, { "id": "roadname_major", "type": "symbol", "source": "carto", "source-layer": "transportation_name", "minzoom": 13, "filter": [ "all", [ "in", "class", "trunk", "motorway" ] ], "layout": { "symbol-placement": "line", "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ], "text-size": { "stops": [ [ 14, 10 ], [ 15, 10 ], [ 16, 11 ], [ 18, 12 ] ] }, "text-field": "{name}", "symbol-avoid-edges": false, "symbol-spacing": { "stops": [ [ 6, 200 ], [ 16, 250 ] ] }, "text-pitch-alignment": "auto", "text-rotation-alignment": "auto", "text-justify": "center", "text-letter-spacing": { "stops": [ [ 13, 0 ], [ 16, 0.2 ] ] } }, "paint": { "text-color": "#838383", "text-halo-color": "#fff", "text-halo-width": 1 } }, { "id": "housenumber", "type": "symbol", "source": "carto", "source-layer": "housenumber", "minzoom": 17, "maxzoom": 24, "layout": { "text-field": "{housenumber}", "text-size": { "stops": [ [ 17, 9 ], [ 18, 11 ] ] }, "text-font": [ "Montserrat Regular", "Open Sans Regular", "Noto Sans Regular", "HanWangHeiLight Regular", "NanumBarunGothic Regular" ] }, "paint": { "text-halo-color": "transparent", "text-color": "transparent", "text-halo-width": 0.75 } } ], "id": "voyager", "owner": "Carto" } ================================================ FILE: examples/maplibre/side-by-side/README.md ================================================ # Example: Side By Side Demonstrates how to synchronize two maps with react-maplibre. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/side-by-side/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/side-by-side/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/side-by-side/src/app.tsx ================================================ /* global window */ import * as React from 'react'; import {useState, useCallback, useMemo} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import ControlPanel, {Mode} from './control-panel'; const LeftMapStyle: React.CSSProperties = { position: 'absolute', width: '50%', height: '100%' }; const RightMapStyle: React.CSSProperties = { position: 'absolute', left: '50%', width: '50%', height: '100%' }; export default function App() { const [viewState, setViewState] = useState({ longitude: -122.43, latitude: 37.78, zoom: 12, pitch: 30 }); const [mode, setMode] = useState('side-by-side'); const onMove = useCallback(evt => setViewState(evt.viewState), []); const width = typeof window === 'undefined' ? 100 : window.innerWidth; const leftMapPadding = useMemo(() => { return {left: mode === 'split-screen' ? width / 2 : 0, top: 0, right: 0, bottom: 0}; }, [width, mode]); const rightMapPadding = useMemo(() => { return {right: mode === 'split-screen' ? width / 2 : 0, top: 0, left: 0, bottom: 0}; }, [width, mode]); return ( <>
); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/side-by-side/src/control-panel.tsx ================================================ import * as React from 'react'; import {useCallback} from 'react'; export type Mode = 'side-by-side' | 'split-screen'; function ControlPanel(props: {mode: Mode; onModeChange: (newMode: Mode) => void}) { const onModeChange = useCallback( evt => { props.onModeChange(evt.target.value as Mode); }, [props.onModeChange] ); return (

Side by Side

Synchronize two maps.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/side-by-side/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/terrain/README.md ================================================ # Example: 3D Terrain This app reproduces Maplibre's [3D terrain](https://maplibre.org/maplibre-gl-js/docs/examples/3d-terrain/) example. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/terrain/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/terrain/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/terrain/src/app.tsx ================================================ import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer, TerrainControl} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; import type {Terrain, Sky} from 'react-map-gl/maplibre'; const sky: Sky = { 'sky-color': '#80ccff', 'sky-horizon-blend': 0.5, 'horizon-color': '#ccddff', 'horizon-fog-blend': 0.5, 'fog-color': '#fcf0dd', 'fog-ground-blend': 0.2 }; const terrain: Terrain = {source: 'terrain-dem', exaggeration: 1.5}; export default function App() { return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/terrain/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

3D Terrain

Add 3D terrain and sky to a map.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/terrain/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/viewport-animation/README.md ================================================ # Example: Viewport Animation This example showcases how to transition smoothly between one viewport to another. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/viewport-animation/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/viewport-animation/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0", "maplibre-gl": "^5.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/viewport-animation/src/app.tsx ================================================ import * as React from 'react'; import {useRef, useCallback} from 'react'; import {createRoot} from 'react-dom/client'; import {Map, MapRef} from 'react-map-gl/maplibre'; import ControlPanel from './control-panel'; const initialViewState = { latitude: 37.7751, longitude: -122.4193, zoom: 11, bearing: 0, pitch: 0 }; export default function App() { const mapRef = useRef(); const onSelectCity = useCallback(({longitude, latitude}) => { mapRef.current?.flyTo({center: [longitude, latitude], duration: 2000}); }, []); return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/viewport-animation/src/control-panel.tsx ================================================ import * as React from 'react'; import CITIES from '../../../.data/cities.json'; function ControlPanel(props) { return (

Camera Transition

Smooth animate of the viewport.


{CITIES.filter(city => city.state === 'California').map((city, index) => (
props.onSelectCity(city)} />
))}
); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/viewport-animation/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/maplibre/zoom-to-bounds/README.md ================================================ # Example: Zoom To Bounds Demonstrates how to zoom to a bounding box with react-maplibre. ## Usage ```bash npm i npm run start ``` ================================================ FILE: examples/maplibre/zoom-to-bounds/index.html ================================================ react-maplibre Example
================================================ FILE: examples/maplibre/zoom-to-bounds/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../vite.config.local.js", "build": "vite build" }, "dependencies": { "@turf/bbox": "^6.5.0", "maplibre-gl": "^5.0.0", "react": "^18.0.0", "react-dom": "^18.0.0", "react-map-gl": "^8.0.0" }, "devDependencies": { "typescript": "^5.0.0", "vite": "^4.0.0" } } ================================================ FILE: examples/maplibre/zoom-to-bounds/src/app.tsx ================================================ import * as React from 'react'; import {useRef} from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from 'react-map-gl/maplibre'; import bbox from '@turf/bbox'; import ControlPanel from './control-panel'; import MAP_STYLE from './map-style'; import type {MapStyle, MapRef, MapLayerMouseEvent} from 'react-map-gl/maplibre'; export default function App() { const mapRef = useRef(); const onClick = (event: MapLayerMouseEvent) => { const feature = event.features[0]; if (feature) { // calculate the bounding box of the feature const [minLng, minLat, maxLng, maxLat] = bbox(feature); mapRef.current.fitBounds( [ [minLng, minLat], [maxLng, maxLat] ], {padding: 40, duration: 1000} ); } }; return ( <> ); } export function renderToDom(container) { createRoot(container).render(); } ================================================ FILE: examples/maplibre/zoom-to-bounds/src/control-panel.tsx ================================================ import * as React from 'react'; function ControlPanel() { return (

Zoom to Bounding Box

Click on a San Fransisco Neighborhood to zoom in.

); } export default React.memo(ControlPanel); ================================================ FILE: examples/maplibre/zoom-to-bounds/src/map-style.tsx ================================================ import type { GeoJSONSourceSpecification, FillLayerSpecification, LineLayerSpecification } from 'react-map-gl/maplibre'; import MAP_STYLE from '../../map-style-basic-v8.json'; const sfNeighborhoods: GeoJSONSourceSpecification = { type: 'geojson', data: 'https://raw.githubusercontent.com/visgl/react-map-gl/master/examples/.data/feature-example-sf.json' }; const fillLayer: FillLayerSpecification = { id: 'sf-neighborhoods-fill', source: 'sf-neighborhoods', type: 'fill', paint: { 'fill-outline-color': '#0040c8', 'fill-color': '#fff', 'fill-opacity': 0 } }; const lineLayer: LineLayerSpecification = { id: 'sf-neighborhoods-outline', source: 'sf-neighborhoods', type: 'line', paint: { 'line-width': 2, 'line-color': '#0080ef' } }; // Make a copy of the map style export default { ...MAP_STYLE, sources: { ...MAP_STYLE.sources, ['sf-neighborhoods']: sfNeighborhoods }, layers: [...MAP_STYLE.layers, fillLayer, lineLayer] }; ================================================ FILE: examples/maplibre/zoom-to-bounds/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "moduleResolution": "node", "module": "ES2020", "sourceMap": true } } ================================================ FILE: examples/vite.config.local.js ================================================ import {defineConfig} from 'vite'; import {join} from 'path'; const rootDir = join(__dirname, '..'); /** https://vitejs.dev/config/ */ export default defineConfig(async () => { return { resolve: { alias: { // Use root dependencies 'react-map-gl/mapbox': join(rootDir, './modules/react-mapbox/src'), 'react-map-gl/maplibre': join(rootDir, './modules/react-maplibre/src'), react: join(rootDir, './node_modules/react'), 'react-dom': join(rootDir, './node_modules/react-dom') } }, define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) }, server: { open: true, port: 8080 }, optimizeDeps: { esbuildOptions: {target: 'es2020'} } }; }); ================================================ FILE: index.html ================================================ react-map-gl unit tests ================================================ FILE: lerna.json ================================================ { "version": "8.1.0-alpha.2", "npmClient": "yarn", "packages": [ "modules/*" ] } ================================================ FILE: modules/main/package.json ================================================ { "name": "react-map-gl", "description": "React components for MapLibre GL JS and Mapbox GL JS", "version": "8.1.0-alpha.2", "keywords": [ "mapbox", "maplibre", "mapbox-gl", "maplibre-gl", "react" ], "repository": { "type": "git", "url": "https://github.com/visgl/react-map-gl.git" }, "license": "MIT", "type": "module", "exports": { "./mapbox": { "types": "./dist/mapbox.d.ts", "require": "./dist/mapbox.cjs", "import": "./dist/mapbox.js" }, "./maplibre": { "types": "./dist/maplibre.d.ts", "require": "./dist/maplibre.cjs", "import": "./dist/maplibre.js" }, "./mapbox-legacy": { "types": "./dist/mapbox-legacy/index.d.ts", "require": "./dist/mapbox-legacy/index.cjs", "import": "./dist/mapbox-legacy/index.js" } }, "typesVersions": { "*": { "mapbox": [ "./dist/mapbox.d.ts" ], "maplibre": [ "./dist/maplibre.d.ts" ], "mapbox-legacy": [ "./dist/mapbox-legacy/index.d.ts" ] } }, "files": [ "src", "dist", "README.md" ], "dependencies": { "@vis.gl/react-mapbox": "8.1.0-alpha.2", "@vis.gl/react-maplibre": "8.1.0-alpha.2" }, "devDependencies": { "@types/mapbox-gl": "3.4.0", "mapbox-gl": "1.13.0" }, "peerDependencies": { "mapbox-gl": ">=1.13.0", "maplibre-gl": ">=1.13.0", "react": ">=16.3.0", "react-dom": ">=16.3.0" }, "peerDependenciesMeta": { "mapbox-gl": { "optional": true }, "maplibre-gl": { "optional": true } } } ================================================ FILE: modules/main/src/mapbox-legacy/components/attribution-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, AttributionControlOptions} from '../types/lib'; export type AttributionControlProps = AttributionControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _AttributionControl(props: AttributionControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { position: props.position }); useEffect(() => { // @ts-expect-error accessing private member applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const AttributionControl = memo(_AttributionControl); ================================================ FILE: modules/main/src/mapbox-legacy/components/fullscreen-control.ts ================================================ /* global document */ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, FullscreenControlOptions} from '../types/lib'; export type FullscreenControlProps = Omit & { /** Id of the DOM element which should be made full screen. By default, the map container * element will be made full screen. */ containerId?: string; /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _FullscreenControl(props: FullscreenControlProps) { const ctrl = useControl( ({mapLib}) => new mapLib.FullscreenControl({ container: props.containerId && document.getElementById(props.containerId) }), {position: props.position} ); useEffect(() => { // @ts-expect-error accessing private member applyReactStyle(ctrl._controlContainer, props.style); }, [props.style]); return null; } export const FullscreenControl = memo(_FullscreenControl); ================================================ FILE: modules/main/src/mapbox-legacy/components/geolocate-control.ts ================================================ import * as React from 'react'; import {useImperativeHandle, useRef, useEffect, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type { ControlPosition, GeolocateControlInstance, GeolocateControlOptions } from '../types/lib'; import type {GeolocateEvent, GeolocateResultEvent, GeolocateErrorEvent} from '../types/events'; export type GeolocateControlProps = GeolocateControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; /** Called on each Geolocation API position update that returned as success. */ onGeolocate?: (e: GeolocateResultEvent) => void; /** Called on each Geolocation API position update that returned as an error. */ onError?: (e: GeolocateErrorEvent) => void; /** Called on each Geolocation API position update that returned as success but user position * is out of map `maxBounds`. */ onOutOfMaxBounds?: (e: GeolocateResultEvent) => void; /** Called when the GeolocateControl changes to the active lock state. */ onTrackUserLocationStart?: (e: GeolocateEvent) => void; /** Called when the GeolocateControl changes to the background state. */ onTrackUserLocationEnd?: (e: GeolocateEvent) => void; }; function _GeolocateControl(props: GeolocateControlProps, ref: React.Ref) { const thisRef = useRef({props}); const ctrl = useControl( ({mapLib}) => { const gc = new mapLib.GeolocateControl(props); // Hack: fix GeolocateControl reuse // When using React strict mode, the component is mounted twice. // GeolocateControl's UI creation is asynchronous. Removing and adding it back causes the UI to be initialized twice. // @ts-expect-error accessing private method const setupUI = gc._setupUI.bind(gc); // @ts-expect-error overriding private method gc._setupUI = args => { // @ts-expect-error accessing private member if (!gc._container.hasChildNodes()) { setupUI(args); } }; gc.on('geolocate', e => { thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent); }); gc.on('error', e => { thisRef.current.props.onError?.(e as GeolocateErrorEvent); }); gc.on('outofmaxbounds', e => { thisRef.current.props.onOutOfMaxBounds?.(e as GeolocateResultEvent); }); gc.on('trackuserlocationstart', e => { thisRef.current.props.onTrackUserLocationStart?.(e as GeolocateEvent); }); gc.on('trackuserlocationend', e => { thisRef.current.props.onTrackUserLocationEnd?.(e as GeolocateEvent); }); return gc; }, {position: props.position} ); thisRef.current.props = props; useImperativeHandle(ref, () => ctrl, []); useEffect(() => { // @ts-expect-error accessing private member applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const GeolocateControl = memo(forwardRef(_GeolocateControl)); ================================================ FILE: modules/main/src/mapbox-legacy/components/layer.ts ================================================ import {useContext, useEffect, useMemo, useState, useRef} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type {MapInstance, CustomLayerInterface} from '../types/lib'; import type {LayerSpecification} from '../types/style-spec'; // Omiting property from a union type, see // https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230 type OptionalId = T extends {id: string} ? Omit & {id?: string} : T; type OptionalSource = T extends {source: string} ? Omit & {source?: string} : T; export type LayerProps = (OptionalSource> | CustomLayerInterface) & { /** If set, the layer will be inserted before the specified layer */ beforeId?: string; }; /* eslint-disable complexity, max-statements */ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: LayerProps) { assert(props.id === prevProps.id, 'layer id changed'); assert(props.type === prevProps.type, 'layer type changed'); if (props.type === 'custom' || prevProps.type === 'custom') { return; } // @ts-ignore filter does not exist in some Layer types const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props; if (beforeId !== prevProps.beforeId) { map.moveLayer(id, beforeId); } if (layout !== prevProps.layout) { const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { map.setLayoutProperty(id, key as any, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { map.setLayoutProperty(id, key as any, undefined); } } } if (paint !== prevProps.paint) { const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { map.setPaintProperty(id, key as any, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { map.setPaintProperty(id, key as any, undefined); } } } // @ts-ignore filter does not exist in some Layer types if (!deepEqual(filter, prevProps.filter)) { map.setFilter(id, filter); } if (minzoom !== prevProps.minzoom || maxzoom !== prevProps.maxzoom) { map.setLayerZoomRange(id, minzoom, maxzoom); } } function createLayer(map: MapInstance, id: string, props: LayerProps) { // @ts-ignore if (map.style && map.style._loaded && (!('source' in props) || map.getSource(props.source))) { const options: LayerProps = {...props, id}; delete options.beforeId; // @ts-ignore map.addLayer(options, props.beforeId); } } /* eslint-enable complexity, max-statements */ let layerCounter = 0; export function Layer(props: LayerProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-layer-${layerCounter++}`, []); useEffect(() => { if (map) { const forceUpdate = () => setStyleLoaded(version => version + 1); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getLayer(id)) { map.removeLayer(id); } }; } return undefined; }, [map]); // @ts-ignore const layer = map && map.style && map.getLayer(id); if (layer) { try { updateLayer(map, id, props, propsRef.current); } catch (error) { console.warn(error); // eslint-disable-line } } else { createLayer(map, id, props); } // Store last rendered props propsRef.current = props; return null; } ================================================ FILE: modules/main/src/mapbox-legacy/components/map.tsx ================================================ import * as React from 'react'; import {useState, useRef, useEffect, useContext, useMemo, useImperativeHandle} from 'react'; import {MountedMapsContext} from './use-map'; import Mapbox, {MapboxProps} from '../mapbox/mapbox'; import createRef, {MapRef} from '../mapbox/create-ref'; import type {CSSProperties} from 'react'; import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect'; import setGlobals, {GlobalSettings} from '../utils/set-globals'; import type {MapLib, MapOptions} from '../types/lib'; export type MapContextValue = { mapLib: MapLib; map: MapRef; }; export const MapContext = React.createContext(null); type MapInitOptions = Omit< MapOptions, 'style' | 'container' | 'bounds' | 'fitBoundsOptions' | 'center' >; export type MapProps = MapInitOptions & MapboxProps & GlobalSettings & { mapLib?: MapLib | Promise; reuseMaps?: boolean; /** Map container id */ id?: string; /** Map container CSS style */ style?: CSSProperties; children?: any; }; function _Map(props: MapProps, ref: React.Ref) { const mountedMapsContext = useContext(MountedMapsContext); const [mapInstance, setMapInstance] = useState(null); const containerRef = useRef(); const {current: contextValue} = useRef({mapLib: null, map: null}); useEffect(() => { const mapLib = props.mapLib; let isMounted = true; let mapbox: Mapbox; Promise.resolve(mapLib || import('mapbox-gl')) .then((module: MapLib | {default: MapLib}) => { if (!isMounted) { return; } if (!module) { throw new Error('Invalid mapLib'); } const mapboxgl = 'Map' in module ? module : module.default; if (!mapboxgl.Map) { throw new Error('Invalid mapLib'); } setGlobals(mapboxgl, props); if (props.reuseMaps) { mapbox = Mapbox.reuse(props, containerRef.current); } if (!mapbox) { mapbox = new Mapbox(mapboxgl.Map, props, containerRef.current); } contextValue.map = createRef(mapbox); contextValue.mapLib = mapboxgl; setMapInstance(mapbox); mountedMapsContext?.onMapMount(contextValue.map, props.id); }) .catch(error => { const {onError} = props; if (onError) { onError({ type: 'error', target: null, error, originalEvent: error }); } else { console.error(error); // eslint-disable-line } }); return () => { isMounted = false; if (mapbox) { mountedMapsContext?.onMapUnmount(props.id); if (props.reuseMaps) { mapbox.recycle(); } else { mapbox.destroy(); } } }; }, []); useIsomorphicLayoutEffect(() => { if (mapInstance) { mapInstance.setProps(props); } }); useImperativeHandle(ref, () => contextValue.map, [mapInstance]); const style: CSSProperties = useMemo( () => ({ position: 'relative', width: '100%', height: '100%', ...props.style }), [props.style] ); const CHILD_CONTAINER_STYLE = { height: '100%' }; return (
{mapInstance && (
{props.children}
)}
); } export const Map = React.forwardRef(_Map); ================================================ FILE: modules/main/src/mapbox-legacy/components/marker.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance, MarkerInstance, MarkerOptions} from '../types/lib'; import type {MarkerEvent, MarkerDragEvent} from '../types/events'; import {MapContext} from './map'; import {arePointsEqual} from '../utils/deep-equal'; export type MarkerProps = MarkerOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; popup?: PopupInstance; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onClick?: (e: MarkerEvent) => void; onDragStart?: (e: MarkerDragEvent) => void; onDrag?: (e: MarkerDragEvent) => void; onDragEnd?: (e: MarkerDragEvent) => void; children?: React.ReactNode; }; /* eslint-disable complexity,max-statements */ export const Marker = memo( forwardRef((props: MarkerProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const thisRef = useRef({props}); thisRef.current.props = props; const marker: MarkerInstance = useMemo(() => { let hasChildren = false; React.Children.forEach(props.children, el => { if (el) { hasChildren = true; } }); const options = { ...props, element: hasChildren ? document.createElement('div') : null }; const mk = new mapLib.Marker(options); mk.setLngLat([props.longitude, props.latitude]); mk.getElement().addEventListener('click', (e: MouseEvent) => { thisRef.current.props.onClick?.({ type: 'click', target: mk, originalEvent: e }); }); mk.on('dragstart', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragStart?.(evt); }); mk.on('drag', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDrag?.(evt); }); mk.on('dragend', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragEnd?.(evt); }); return mk; }, []); useEffect(() => { marker.addTo(map.getMap()); return () => { marker.remove(); }; }, []); const { longitude, latitude, offset, style, draggable = false, popup = null, rotation = 0, rotationAlignment = 'auto', pitchAlignment = 'auto' } = props; useEffect(() => { applyReactStyle(marker.getElement(), style); }, [style]); useImperativeHandle(ref, () => marker, []); if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) { marker.setLngLat([longitude, latitude]); } if (offset && !arePointsEqual(marker.getOffset(), offset)) { marker.setOffset(offset); } if (marker.isDraggable() !== draggable) { marker.setDraggable(draggable); } if (marker.getRotation() !== rotation) { marker.setRotation(rotation); } if (marker.getRotationAlignment() !== rotationAlignment) { marker.setRotationAlignment(rotationAlignment); } if (marker.getPitchAlignment() !== pitchAlignment) { marker.setPitchAlignment(pitchAlignment); } if (marker.getPopup() !== popup) { marker.setPopup(popup); } return createPortal(props.children, marker.getElement()); }) ); ================================================ FILE: modules/main/src/mapbox-legacy/components/navigation-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, NavigationControlOptions} from '../types/lib'; export type NavigationControlProps = NavigationControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _NavigationControl(props: NavigationControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { position: props.position }); useEffect(() => { // @ts-expect-error accessing private member applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const NavigationControl = memo(_NavigationControl); ================================================ FILE: modules/main/src/mapbox-legacy/components/popup.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance as _PopupInstance, PopupOptions} from '../types/lib'; import type {PopupEvent} from '../types/events'; import {MapContext} from './map'; import {deepEqual} from '../utils/deep-equal'; export type PopupProps = PopupOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onOpen?: (e: PopupEvent) => void; onClose?: (e: PopupEvent) => void; children?: React.ReactNode; }; // Adapted from https://github.com/mapbox/mapbox-gl-js/blob/v1.13.0/src/ui/popup.js function getClassList(className: string) { return new Set(className ? className.trim().split(/\s+/) : []); } type PopupInstance = _PopupInstance & { options: PopupOptions; }; /* eslint-disable complexity,max-statements */ export const Popup = memo( forwardRef((props: PopupProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const container = useMemo(() => { return document.createElement('div'); }, []); const thisRef = useRef({props}); thisRef.current.props = props; const popup = useMemo(() => { const options = {...props}; const pp = new mapLib.Popup(options); pp.setLngLat([props.longitude, props.latitude]); pp.once('open', e => { thisRef.current.props.onOpen?.(e as PopupEvent); }); return pp as PopupInstance; }, []); useEffect(() => { const onClose = e => { thisRef.current.props.onClose?.(e as PopupEvent); }; popup.on('close', onClose); popup.setDOMContent(container).addTo(map.getMap()); return () => { // https://github.com/visgl/react-map-gl/issues/1825 // onClose should not be fired if the popup is removed by unmounting // When using React strict mode, the component is mounted twice. // Firing the onClose callback here would be a false signal to remove the component. popup.off('close', onClose); if (popup.isOpen()) { popup.remove(); } }; }, []); useEffect(() => { applyReactStyle(popup.getElement(), props.style); }, [props.style]); useImperativeHandle(ref, () => popup, []); if (popup.isOpen()) { if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) { popup.setLngLat([props.longitude, props.latitude]); } if (props.offset && !deepEqual(popup.options.offset, props.offset)) { popup.setOffset(props.offset); } if (popup.options.anchor !== props.anchor || popup.options.maxWidth !== props.maxWidth) { popup.options.anchor = props.anchor; popup.setMaxWidth(props.maxWidth); } if (popup.options.className !== props.className) { const prevClassList = getClassList(popup.options.className); const nextClassList = getClassList(props.className); for (const c of prevClassList) { if (!nextClassList.has(c)) { popup.removeClassName(c); } } for (const c of nextClassList) { if (!prevClassList.has(c)) { popup.addClassName(c); } } popup.options.className = props.className; } } return createPortal(props.children, container); }) ); ================================================ FILE: modules/main/src/mapbox-legacy/components/scale-control.ts ================================================ import * as React from 'react'; import {useEffect, useRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, ScaleControlOptions} from '../types/lib'; export type ScaleControlProps = ScaleControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _ScaleControl(props: ScaleControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.ScaleControl(props), { position: props.position }); const propsRef = useRef(props); const prevProps = propsRef.current; propsRef.current = props; const {style} = props; if (props.maxWidth !== undefined && props.maxWidth !== prevProps.maxWidth) { // @ts-expect-error accessing private member ctrl.options.maxWidth = props.maxWidth; } if (props.unit !== undefined && props.unit !== prevProps.unit) { ctrl.setUnit(props.unit as any); } useEffect(() => { // @ts-expect-error accessing private member applyReactStyle(ctrl._container, style); }, [style]); return null; } export const ScaleControl = memo(_ScaleControl); ================================================ FILE: modules/main/src/mapbox-legacy/components/source.ts ================================================ import * as React from 'react'; import {useContext, useEffect, useMemo, useState, useRef, cloneElement} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type { GeoJSONSourceImplementation, ImageSourceImplemtation, AnySourceImplementation } from '../types/internal'; import type { SourceSpecification, ImageSourceSpecification, VectorSourceSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; export type SourceProps = SourceSpecification & { id?: string; children?: any; }; let sourceCounter = 0; function createSource(map: MapInstance, id: string, props: SourceProps) { // @ts-ignore if (map.style && map.style._loaded) { const options = {...props}; delete options.id; delete options.children; // @ts-ignore map.addSource(id, options); return map.getSource(id); } return null; } /* eslint-disable complexity */ function updateSource(source: AnySourceImplementation, props: SourceProps, prevProps: SourceProps) { assert(props.id === prevProps.id, 'source id changed'); assert(props.type === prevProps.type, 'source type changed'); let changedKey = ''; let changedKeyCount = 0; for (const key in props) { if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) { changedKey = key; changedKeyCount++; } } if (!changedKeyCount) { return; } const type = props.type; if (type === 'geojson') { (source as GeoJSONSourceImplementation).setData(props.data as any); } else if (type === 'image') { (source as ImageSourceImplemtation).updateImage({ url: props.url, coordinates: props.coordinates }); } else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') { source.setCoordinates((props as unknown as ImageSourceSpecification).coordinates); } else if ('setUrl' in source && changedKey === 'url') { source.setUrl((props as VectorSourceSpecification).url); } else if ('setTiles' in source && changedKey === 'tiles') { source.setTiles((props as VectorSourceSpecification).tiles); } else { // eslint-disable-next-line console.warn(`Unable to update prop: ${changedKey}`); } } /* eslint-enable complexity */ export function Source(props: SourceProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-source-${sourceCounter++}`, []); useEffect(() => { if (map) { /* global setTimeout */ const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getSource(id)) { // Parent effects are destroyed before child ones, see // https://github.com/facebook/react/issues/16728 // Source can only be removed after all child layers are removed const allLayers = map.getStyle()?.layers; if (allLayers) { for (const layer of allLayers) { // @ts-ignore (2339) source does not exist on all layer types if (layer.source === id) { map.removeLayer(layer.id); } } } map.removeSource(id); } }; } return undefined; }, [map]); // @ts-ignore let source = map && map.style && map.getSource(id); if (source) { updateSource(source, props, propsRef.current); } else { source = createSource(map, id, props); } propsRef.current = props; return ( (source && React.Children.map( props.children, child => child && cloneElement(child, { source: id }) )) || null ); } ================================================ FILE: modules/main/src/mapbox-legacy/components/use-control.ts ================================================ import {useContext, useMemo, useEffect} from 'react'; import type {IControl, ControlPosition} from '../types/lib'; import {MapContext} from './map'; import type {MapContextValue} from './map'; type ControlOptions = { position?: ControlPosition; }; export function useControl( onCreate: (context: MapContextValue) => T, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onAdd: (context: MapContextValue) => void, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, arg1?: ((context: MapContextValue) => void) | ControlOptions, arg2?: ((context: MapContextValue) => void) | ControlOptions, arg3?: ControlOptions ): T { const context = useContext(MapContext); const ctrl = useMemo(() => onCreate(context), []); useEffect(() => { const opts = (arg3 || arg2 || arg1) as ControlOptions; const onAdd = typeof arg1 === 'function' && typeof arg2 === 'function' ? arg1 : null; const onRemove = typeof arg2 === 'function' ? arg2 : typeof arg1 === 'function' ? arg1 : null; const {map} = context; if (!map.hasControl(ctrl)) { map.addControl(ctrl, opts?.position); if (onAdd) { onAdd(context); } } return () => { if (onRemove) { onRemove(context); } // Map might have been removed (parent effects are destroyed before child ones) if (map.hasControl(ctrl)) { map.removeControl(ctrl); } }; }, []); return ctrl; } ================================================ FILE: modules/main/src/mapbox-legacy/components/use-map.tsx ================================================ import * as React from 'react'; import {useState, useCallback, useMemo, useContext} from 'react'; import {MapRef} from '../mapbox/create-ref'; import {MapContext} from './map'; type MountedMapsContextValue = { maps: {[id: string]: MapRef}; onMapMount: (map: MapRef, id: string) => void; onMapUnmount: (id: string) => void; }; export const MountedMapsContext = React.createContext(null); export const MapProvider: React.FC<{children?: React.ReactNode}> = props => { const [maps, setMaps] = useState<{[id: string]: MapRef}>({}); const onMapMount = useCallback((map: MapRef, id: string = 'default') => { setMaps(currMaps => { if (id === 'current') { throw new Error("'current' cannot be used as map id"); } if (currMaps[id]) { throw new Error(`Multiple maps with the same id: ${id}`); } return {...currMaps, [id]: map}; }); }, []); const onMapUnmount = useCallback((id: string = 'default') => { setMaps(currMaps => { if (currMaps[id]) { const nextMaps = {...currMaps}; delete nextMaps[id]; return nextMaps; } return currMaps; }); }, []); return ( {props.children} ); }; export type MapCollection = { [id: string]: MapRef | undefined; current?: MapRef; }; export function useMap(): MapCollection { const maps = useContext(MountedMapsContext)?.maps; const currentMap = useContext(MapContext); const mapsWithCurrent = useMemo(() => { return {...maps, current: currentMap?.map}; }, [maps, currentMap]); return mapsWithCurrent as MapCollection; } ================================================ FILE: modules/main/src/mapbox-legacy/index.ts ================================================ import {Map} from './components/map'; export {Map}; export default Map; export {Marker} from './components/marker'; export {Popup} from './components/popup'; export {AttributionControl} from './components/attribution-control'; export {FullscreenControl} from './components/fullscreen-control'; export {GeolocateControl} from './components/geolocate-control'; export {NavigationControl} from './components/navigation-control'; export {ScaleControl} from './components/scale-control'; export {Source} from './components/source'; export {Layer} from './components/layer'; export {useControl} from './components/use-control'; export {MapProvider, useMap} from './components/use-map'; export type {MapProps} from './components/map'; export type {MapRef} from './mapbox/create-ref'; export type {MarkerProps} from './components/marker'; export type {PopupProps} from './components/popup'; export type {AttributionControlProps} from './components/attribution-control'; export type {FullscreenControlProps} from './components/fullscreen-control'; export type {GeolocateControlProps} from './components/geolocate-control'; export type {NavigationControlProps} from './components/navigation-control'; export type {ScaleControlProps} from './components/scale-control'; export type {SourceProps} from './components/source'; export type {LayerProps} from './components/layer'; // Types export * from './types/common'; export * from './types/events'; export * from './types/lib'; export * from './types/style-spec'; ================================================ FILE: modules/main/src/mapbox-legacy/mapbox/create-ref.ts ================================================ import type {MapInstance} from '../types/lib'; import type {MapInstanceInternal} from '../types/internal'; import {LngLatLike, PointLike} from '../types/common'; import type Mapbox from './mapbox'; /** These methods may break the react binding if called directly */ const skipMethods = [ 'setMaxBounds', 'setMinZoom', 'setMaxZoom', 'setMinPitch', 'setMaxPitch', 'setRenderWorldCopies', 'setProjection', 'setStyle', 'addSource', 'removeSource', 'addLayer', 'removeLayer', 'setLayerZoomRange', 'setFilter', 'setPaintProperty', 'setLayoutProperty', 'setLight', 'setTerrain', 'setFog', 'remove' ] as const; export type MapRef = { getMap(): MapInstance; } & Omit; export default function createRef(mapInstance: Mapbox): MapRef | null { if (!mapInstance) { return null; } const map = mapInstance.map as MapInstanceInternal; const ref: any = { getMap: () => mapInstance.map, // Overwrite getters to use our shadow transform getCenter: () => mapInstance.transform.center, getZoom: () => mapInstance.transform.zoom, getBearing: () => mapInstance.transform.bearing, getPitch: () => mapInstance.transform.pitch, getPadding: () => mapInstance.transform.padding, getBounds: () => mapInstance.transform.getBounds(), project: (lnglat: LngLatLike) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.project(lnglat); map.transform = tr; return result; }, unproject: (point: PointLike) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.unproject(point); map.transform = tr; return result; }, // options diverge between mapbox and maplibre queryTerrainElevation: (lnglat: LngLatLike, options?: any) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.queryTerrainElevation(lnglat, options); map.transform = tr; return result; }, queryRenderedFeatures: (geometry?: any, options?: any) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.queryRenderedFeatures(geometry, options); map.transform = tr; return result; } }; for (const key of getMethodNames(map)) { // @ts-expect-error if (!(key in ref) && !skipMethods.includes(key)) { ref[key] = map[key].bind(map); } } return ref; } function getMethodNames(obj: Object) { const result = new Set(); let proto = obj; while (proto) { for (const key of Object.getOwnPropertyNames(proto)) { if ( key[0] !== '_' && typeof obj[key] === 'function' && key !== 'fire' && key !== 'setEventedParent' ) { result.add(key); } } proto = Object.getPrototypeOf(proto); } return Array.from(result); } ================================================ FILE: modules/main/src/mapbox-legacy/mapbox/mapbox.ts ================================================ import { transformToViewState, applyViewStateToTransform, cloneTransform, syncProjection } from '../utils/transform'; import {normalizeStyle} from '../utils/style-utils'; import {deepEqual} from '../utils/deep-equal'; import type { ViewState, Point, PointLike, PaddingOptions, ImmutableLike, LngLatBoundsLike, MapGeoJSONFeature } from '../types/common'; import type { StyleSpecification, LightSpecification, TerrainSpecification, FogSpecification, ProjectionSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; import type {Transform, MapInstanceInternal} from '../types/internal'; import type { MapCallbacks, ViewStateChangeEvent, MapEvent, ErrorEvent, MapMouseEvent } from '../types/events'; export type MapboxProps = Partial & MapCallbacks & { // Init options mapboxAccessToken?: string; /** Camera options used when constructing the Map instance */ initialViewState?: Partial & { /** The initial bounds of the map. If bounds is specified, it overrides longitude, latitude and zoom options. */ bounds?: LngLatBoundsLike; /** A fitBounds options object to use only when setting the bounds option. */ fitBoundsOptions?: { offset?: PointLike; minZoom?: number; maxZoom?: number; padding?: number | PaddingOptions; }; }; /** If provided, render into an external WebGL context */ gl?: WebGLRenderingContext; /** For external controller to override the camera state */ viewState?: ViewState & { width: number; height: number; }; // Styling /** Mapbox style */ mapStyle?: string | StyleSpecification | ImmutableLike; /** Enable diffing when the map style changes * @default true */ styleDiffing?: boolean; /** The projection property of the style. Must conform to the Projection Style Specification. * @default 'mercator' */ projection?: ProjectionSpecification | ProjectionSpecification['name']; /** The fog property of the style. Must conform to the Fog Style Specification . * If `undefined` is provided, removes the fog from the map. */ fog?: FogSpecification; /** Light properties of the map. */ light?: LightSpecification; /** Terrain property of the style. Must conform to the Terrain Style Specification . * If `undefined` is provided, removes terrain from the map. */ terrain?: TerrainSpecification; /** Default layers to query on pointer events */ interactiveLayerIds?: string[]; /** CSS cursor */ cursor?: string; }; const DEFAULT_STYLE = {version: 8, sources: {}, layers: []} as StyleSpecification; const pointerEvents = { mousedown: 'onMouseDown', mouseup: 'onMouseUp', mouseover: 'onMouseOver', mousemove: 'onMouseMove', click: 'onClick', dblclick: 'onDblClick', mouseenter: 'onMouseEnter', mouseleave: 'onMouseLeave', mouseout: 'onMouseOut', contextmenu: 'onContextMenu', touchstart: 'onTouchStart', touchend: 'onTouchEnd', touchmove: 'onTouchMove', touchcancel: 'onTouchCancel' }; const cameraEvents = { movestart: 'onMoveStart', move: 'onMove', moveend: 'onMoveEnd', dragstart: 'onDragStart', drag: 'onDrag', dragend: 'onDragEnd', zoomstart: 'onZoomStart', zoom: 'onZoom', zoomend: 'onZoomEnd', rotatestart: 'onRotateStart', rotate: 'onRotate', rotateend: 'onRotateEnd', pitchstart: 'onPitchStart', pitch: 'onPitch', pitchend: 'onPitchEnd' }; const otherEvents = { wheel: 'onWheel', boxzoomstart: 'onBoxZoomStart', boxzoomend: 'onBoxZoomEnd', boxzoomcancel: 'onBoxZoomCancel', resize: 'onResize', load: 'onLoad', render: 'onRender', idle: 'onIdle', remove: 'onRemove', data: 'onData', styledata: 'onStyleData', sourcedata: 'onSourceData', error: 'onError' }; const settingNames = [ 'minZoom', 'maxZoom', 'minPitch', 'maxPitch', 'maxBounds', 'projection', 'renderWorldCopies' ]; const handlerNames = [ 'scrollZoom', 'boxZoom', 'dragRotate', 'dragPan', 'keyboard', 'doubleClickZoom', 'touchZoomRotate', 'touchPitch' ]; /** * A wrapper for mapbox-gl's Map class */ export default class Mapbox { private _MapClass: {new (options: any): MapInstance}; // mapboxgl.Map instance private _map: MapInstanceInternal = null; // User-supplied props props: MapboxProps; // Mapbox map is stateful. // During method calls/user interactions, map.transform is mutated and // deviate from user-supplied props. // In order to control the map reactively, we shadow the transform // with the one below, which reflects the view state resolved from // both user-supplied props and the underlying state private _renderTransform: Transform; // Internal states private _internalUpdate: boolean = false; private _inRender: boolean = false; private _hoveredFeatures: MapGeoJSONFeature[] = null; private _deferredEvents: { move: boolean; zoom: boolean; pitch: boolean; rotate: boolean; } = { move: false, zoom: false, pitch: false, rotate: false }; static savedMaps: Mapbox[] = []; constructor( MapClass: {new (options: any): MapInstance}, props: MapboxProps, container: HTMLDivElement ) { this._MapClass = MapClass; this.props = props; this._initialize(container); } get map(): MapInstance { return this._map; } get transform(): Transform { return this._renderTransform; } setProps(props: MapboxProps) { const oldProps = this.props; this.props = props; const settingsChanged = this._updateSettings(props, oldProps); if (settingsChanged) { this._createShadowTransform(this._map); } const sizeChanged = this._updateSize(props); const viewStateChanged = this._updateViewState(props, true); this._updateStyle(props, oldProps); this._updateStyleComponents(props, oldProps); this._updateHandlers(props, oldProps); // If 1) view state has changed to match props and // 2) the props change is not triggered by map events, // it's driven by an external state change. Redraw immediately if (settingsChanged || sizeChanged || (viewStateChanged && !this._map.isMoving())) { this.redraw(); } } static reuse(props: MapboxProps, container: HTMLDivElement): Mapbox { const that = Mapbox.savedMaps.pop(); if (!that) { return null; } const map = that.map; // When reusing the saved map, we need to reparent the map(canvas) and other child nodes // intoto the new container from the props. // Step 1: reparenting child nodes from old container to new container const oldContainer = map.getContainer(); container.className = oldContainer.className; while (oldContainer.childNodes.length > 0) { container.appendChild(oldContainer.childNodes[0]); } // Step 2: replace the internal container with new container from the react component // @ts-ignore map._container = container; // Step 4: apply new props that.setProps({...props, styleDiffing: false}); map.resize(); const {initialViewState} = props; if (initialViewState) { if (initialViewState.bounds) { map.fitBounds(initialViewState.bounds, {...initialViewState.fitBoundsOptions, duration: 0}); } else { that._updateViewState(initialViewState, false); } } // Simulate load event if (map.isStyleLoaded()) { map.fire('load'); } else { map.once('styledata', () => map.fire('load')); } // Force reload // @ts-ignore map._update(); return that; } /* eslint-disable complexity,max-statements */ _initialize(container: HTMLDivElement) { const {props} = this; const {mapStyle = DEFAULT_STYLE} = props; const mapOptions = { ...props, ...props.initialViewState, accessToken: props.mapboxAccessToken || getAccessTokenFromEnv() || null, container, style: normalizeStyle(mapStyle) }; const viewState = mapOptions.initialViewState || mapOptions.viewState || mapOptions; Object.assign(mapOptions, { center: [viewState.longitude || 0, viewState.latitude || 0], zoom: viewState.zoom || 0, pitch: viewState.pitch || 0, bearing: viewState.bearing || 0 }); if (props.gl) { // eslint-disable-next-line const getContext = HTMLCanvasElement.prototype.getContext; // Hijack canvas.getContext to return our own WebGLContext // This will be called inside the mapboxgl.Map constructor // @ts-expect-error HTMLCanvasElement.prototype.getContext = () => { // Unhijack immediately HTMLCanvasElement.prototype.getContext = getContext; return props.gl; }; } const map = new this._MapClass(mapOptions) as MapInstanceInternal; // Props that are not part of constructor options if (viewState.padding) { map.setPadding(viewState.padding); } if (props.cursor) { map.getCanvas().style.cursor = props.cursor; } this._createShadowTransform(map); // Hack // Insert code into map's render cycle // eslint-disable-next-line @typescript-eslint/unbound-method const renderMap = map._render; map._render = (arg: number) => { this._inRender = true; renderMap.call(map, arg); this._inRender = false; }; // eslint-disable-next-line @typescript-eslint/unbound-method const runRenderTaskQueue = map._renderTaskQueue.run; map._renderTaskQueue.run = (arg: number) => { runRenderTaskQueue.call(map._renderTaskQueue, arg); this._onBeforeRepaint(); }; map.on('render', () => this._onAfterRepaint()); // Insert code into map's event pipeline // eslint-disable-next-line @typescript-eslint/unbound-method const fireEvent = map.fire; map.fire = this._fireEvent.bind(this, fireEvent); // add listeners map.on('resize', () => { this._renderTransform.resize(map.transform.width, map.transform.height); }); map.on('styledata', () => { this._updateStyleComponents(this.props, {}); // Projection can be set in stylesheet syncProjection(map.transform, this._renderTransform); }); map.on('sourcedata', () => this._updateStyleComponents(this.props, {})); for (const eventName in pointerEvents) { map.on(eventName, this._onPointerEvent); } for (const eventName in cameraEvents) { map.on(eventName, this._onCameraEvent); } for (const eventName in otherEvents) { map.on(eventName, this._onEvent); } this._map = map; } /* eslint-enable complexity,max-statements */ recycle() { // Clean up unnecessary elements before storing for reuse. const container = this.map.getContainer(); const children = container.querySelector('[mapboxgl-children]'); children?.remove(); Mapbox.savedMaps.push(this); } destroy() { this._map.remove(); } // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next // render cycle, which is managed by Mapbox's animation loop. // This removes the synchronization issue caused by requestAnimationFrame. redraw() { const map = this._map as any; // map._render will throw error if style does not exist // https://github.com/mapbox/mapbox-gl-js/blob/fb9fc316da14e99ff4368f3e4faa3888fb43c513 // /src/ui/map.js#L1834 if (!this._inRender && map.style) { // cancel the scheduled update if (map._frame) { map._frame.cancel(); map._frame = null; } // the order is important - render() may schedule another update map._render(); } } _createShadowTransform(map: any) { const renderTransform = cloneTransform(map.transform); map.painter.transform = renderTransform; this._renderTransform = renderTransform; } /* Trigger map resize if size is controlled @param {object} nextProps @returns {bool} true if size has changed */ _updateSize(nextProps: MapboxProps): boolean { // Check if size is controlled const {viewState} = nextProps; if (viewState) { const map = this._map; if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) { map.resize(); return true; } } return false; } // Adapted from map.jumpTo /* Update camera to match props @param {object} nextProps @param {bool} triggerEvents - should fire camera events @returns {bool} true if anything is changed */ _updateViewState(nextProps: MapboxProps, triggerEvents: boolean): boolean { if (this._internalUpdate) { return false; } const map = this._map; const tr = this._renderTransform; // Take a snapshot of the transform before mutation const {zoom, pitch, bearing} = tr; const isMoving = map.isMoving(); if (isMoving) { // All movement of the camera is done relative to the sea level tr.cameraElevationReference = 'sea'; } const changed = applyViewStateToTransform(tr, { ...transformToViewState(map.transform), ...nextProps }); if (isMoving) { // Reset camera reference tr.cameraElevationReference = 'ground'; } if (changed && triggerEvents) { const deferredEvents = this._deferredEvents; // Delay DOM control updates to the next render cycle deferredEvents.move = true; deferredEvents.zoom ||= zoom !== tr.zoom; deferredEvents.rotate ||= bearing !== tr.bearing; deferredEvents.pitch ||= pitch !== tr.pitch; } // Avoid manipulating the real transform when interaction/animation is ongoing // as it would interfere with Mapbox's handlers if (!isMoving) { applyViewStateToTransform(map.transform, nextProps); } return changed; } /* Update camera constraints and projection settings to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateSettings(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; for (const propName of settingNames) { if (propName in nextProps && !deepEqual(nextProps[propName], currProps[propName])) { changed = true; const setter = map[`set${propName[0].toUpperCase()}${propName.slice(1)}`]; setter?.call(map, nextProps[propName]); } } return changed; } /* Update map style to match props @param {object} nextProps @param {object} currProps @returns {bool} true if style is changed */ _updateStyle(nextProps: MapboxProps, currProps: MapboxProps): boolean { if (nextProps.cursor !== currProps.cursor) { this._map.getCanvas().style.cursor = nextProps.cursor || ''; } if (nextProps.mapStyle !== currProps.mapStyle) { const {mapStyle = DEFAULT_STYLE, styleDiffing = true} = nextProps; const options: any = { diff: styleDiffing }; if ('localIdeographFontFamily' in nextProps) { // @ts-ignore Mapbox specific prop options.localIdeographFontFamily = nextProps.localIdeographFontFamily; } this._map.setStyle(normalizeStyle(mapStyle), options); return true; } return false; } /* Update fog, light and terrain to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateStyleComponents(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; if (map.isStyleLoaded()) { if ('light' in nextProps && map.setLight && !deepEqual(nextProps.light, currProps.light)) { changed = true; map.setLight(nextProps.light); } if ('fog' in nextProps && map.setFog && !deepEqual(nextProps.fog, currProps.fog)) { changed = true; map.setFog(nextProps.fog); } if ( 'terrain' in nextProps && map.setTerrain && !deepEqual(nextProps.terrain, currProps.terrain) ) { if (!nextProps.terrain || map.getSource(nextProps.terrain.source)) { changed = true; map.setTerrain(nextProps.terrain); } } } return changed; } /* Update interaction handlers to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateHandlers(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; for (const propName of handlerNames) { const newValue = nextProps[propName] ?? true; const oldValue = currProps[propName] ?? true; if (!deepEqual(newValue, oldValue)) { changed = true; if (newValue) { map[propName].enable(newValue); } else { map[propName].disable(); } } } return changed; } _onEvent = (e: MapEvent) => { // @ts-ignore const cb = this.props[otherEvents[e.type]]; if (cb) { cb(e); } else if (e.type === 'error') { console.error((e as ErrorEvent).error); // eslint-disable-line } }; private _queryRenderedFeatures(point: Point) { const map = this._map; const tr = map.transform; const {interactiveLayerIds = []} = this.props; try { map.transform = this._renderTransform; return map.queryRenderedFeatures(point, { layers: interactiveLayerIds.filter(map.getLayer.bind(map)) }); } catch { // May fail if style is not loaded return []; } finally { map.transform = tr; } } _updateHover(e: MapMouseEvent) { const {props} = this; const shouldTrackHoveredFeatures = props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave); if (shouldTrackHoveredFeatures) { const eventType = e.type; const wasHovering = this._hoveredFeatures?.length > 0; const features = this._queryRenderedFeatures(e.point); const isHovering = features.length > 0; if (!isHovering && wasHovering) { e.type = 'mouseleave'; this._onPointerEvent(e); } this._hoveredFeatures = features; if (isHovering && !wasHovering) { e.type = 'mouseenter'; this._onPointerEvent(e); } e.type = eventType; } else { this._hoveredFeatures = null; } } _onPointerEvent = (e: MapMouseEvent) => { if (e.type === 'mousemove' || e.type === 'mouseout') { this._updateHover(e); } // @ts-ignore const cb = this.props[pointerEvents[e.type]]; if (cb) { if (this.props.interactiveLayerIds && e.type !== 'mouseover' && e.type !== 'mouseout') { e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point); } cb(e); delete e.features; } }; _onCameraEvent = (e: ViewStateChangeEvent) => { if (!this._internalUpdate) { // @ts-ignore const cb = this.props[cameraEvents[e.type]]; if (cb) { cb(e); } } if (e.type in this._deferredEvents) { this._deferredEvents[e.type] = false; } }; _fireEvent(baseFire: Function, event: string | MapEvent, properties?: object) { const map = this._map; const tr = map.transform; const eventType = typeof event === 'string' ? event : event.type; if (eventType === 'move') { this._updateViewState(this.props, false); } if (eventType in cameraEvents) { if (typeof event === 'object') { (event as unknown as ViewStateChangeEvent).viewState = transformToViewState(tr); } if (this._map.isMoving()) { // Replace map.transform with ours during the callbacks map.transform = this._renderTransform; baseFire.call(map, event, properties); map.transform = tr; return map; } } baseFire.call(map, event, properties); return map; } // All camera manipulations are complete, ready to repaint _onBeforeRepaint() { const map = this._map; // If there are camera changes driven by props, invoke camera events so that DOM controls are synced this._internalUpdate = true; for (const eventType in this._deferredEvents) { if (this._deferredEvents[eventType]) { map.fire(eventType); } } this._internalUpdate = false; const tr = this._map.transform; // Make sure camera matches the current props map.transform = this._renderTransform; this._onAfterRepaint = () => { // Mapbox transitions between non-mercator projection and mercator during render time // Copy it back to the other syncProjection(this._renderTransform, tr); // Restores camera state before render/load events are fired map.transform = tr; }; } _onAfterRepaint: () => void; } /** * Access token can be provided via one of: * mapboxAccessToken prop * access_token query parameter * MapboxAccessToken environment variable * REACT_APP_MAPBOX_ACCESS_TOKEN environment variable * @returns access token */ function getAccessTokenFromEnv(): string { let accessToken = null; /* global location, process */ if (typeof location !== 'undefined') { const match = /access_token=([^&\/]*)/.exec(location.search); accessToken = match && match[1]; } // Note: This depends on bundler plugins (e.g. webpack) importing environment correctly try { // eslint-disable-next-line no-process-env accessToken = accessToken || process.env.MapboxAccessToken; } catch { // ignore } try { // eslint-disable-next-line no-process-env accessToken = accessToken || process.env.REACT_APP_MAPBOX_ACCESS_TOKEN; } catch { // ignore } return accessToken; } ================================================ FILE: modules/main/src/mapbox-legacy/types/common.ts ================================================ import type {PaddingOptions} from 'mapbox-gl'; export type { Point, PointLike, LngLat, LngLatLike, LngLatBounds, LngLatBoundsLike, PaddingOptions, MapboxGeoJSONFeature as MapGeoJSONFeature } from 'mapbox-gl'; /* Public */ /** Describes the camera's state */ export type ViewState = { /** Longitude at map center */ longitude: number; /** Latitude at map center */ latitude: number; /** Map zoom level */ zoom: number; /** Map rotation bearing in degrees counter-clockwise from north */ bearing: number; /** Map angle in degrees at which the camera is looking at the ground */ pitch: number; /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ padding: PaddingOptions; }; export interface ImmutableLike { toJS: () => T; } ================================================ FILE: modules/main/src/mapbox-legacy/types/events.ts ================================================ import type {ViewState, LngLat} from './common'; import { MapboxEvent as MapEvent, MapLayerMouseEvent, MapLayerTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent, MapBoxZoomEvent, ErrorEvent, Marker, Popup, GeolocateControl } from 'mapbox-gl'; export type MapCallbacks = { onMouseDown?: (e: MapLayerMouseEvent) => void; onMouseUp?: (e: MapLayerMouseEvent) => void; onMouseOver?: (e: MapLayerMouseEvent) => void; onMouseMove?: (e: MapLayerMouseEvent) => void; onClick?: (e: MapLayerMouseEvent) => void; onDblClick?: (e: MapLayerMouseEvent) => void; onMouseEnter?: (e: MapLayerMouseEvent) => void; onMouseLeave?: (e: MapLayerMouseEvent) => void; onMouseOut?: (e: MapLayerMouseEvent) => void; onContextMenu?: (e: MapLayerMouseEvent) => void; onTouchStart?: (e: MapLayerTouchEvent) => void; onTouchEnd?: (e: MapLayerTouchEvent) => void; onTouchMove?: (e: MapLayerTouchEvent) => void; onTouchCancel?: (e: MapLayerTouchEvent) => void; onMoveStart?: (e: ViewStateChangeEvent) => void; onMove?: (e: ViewStateChangeEvent) => void; onMoveEnd?: (e: ViewStateChangeEvent) => void; onDragStart?: (e: ViewStateChangeEvent) => void; onDrag?: (e: ViewStateChangeEvent) => void; onDragEnd?: (e: ViewStateChangeEvent) => void; onZoomStart?: (e: ViewStateChangeEvent) => void; onZoom?: (e: ViewStateChangeEvent) => void; onZoomEnd?: (e: ViewStateChangeEvent) => void; onRotateStart?: (e: ViewStateChangeEvent) => void; onRotate?: (e: ViewStateChangeEvent) => void; onRotateEnd?: (e: ViewStateChangeEvent) => void; onPitchStart?: (e: ViewStateChangeEvent) => void; onPitch?: (e: ViewStateChangeEvent) => void; onPitchEnd?: (e: ViewStateChangeEvent) => void; onWheel?: (e: MapWheelEvent) => void; onBoxZoomStart?: (e: MapBoxZoomEvent) => void; onBoxZoomEnd?: (e: MapBoxZoomEvent) => void; onBoxZoomCancel?: (e: MapBoxZoomEvent) => void; onResize?: (e: MapEvent) => void; onLoad?: (e: MapEvent) => void; onRender?: (e: MapEvent) => void; onIdle?: (e: MapEvent) => void; onError?: (e: ErrorEvent) => void; onRemove?: (e: MapEvent) => void; onData?: (e: MapStyleDataEvent | MapSourceDataEvent) => void; onStyleData?: (e: MapStyleDataEvent) => void; onSourceData?: (e: MapSourceDataEvent) => void; }; export type { MapEvent, ErrorEvent, MapLayerMouseEvent as MapMouseEvent, MapLayerTouchEvent as MapTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent, MapBoxZoomEvent }; interface IMapEvent { type: string; target: SourceT; originalEvent: OriginalEventT; } export type ViewStateChangeEvent = MapEvent & { type: | 'movestart' | 'move' | 'moveend' | 'zoomstart' | 'zoom' | 'zoomend' | 'rotatestart' | 'rotate' | 'rotateend' | 'dragstart' | 'drag' | 'dragend' | 'pitchstart' | 'pitch' | 'pitchend'; viewState: ViewState; }; export type PopupEvent = { type: 'open' | 'close'; target: Popup; }; export type MarkerEvent = IMapEvent; export type MarkerDragEvent = MarkerEvent & { type: 'dragstart' | 'drag' | 'dragend'; lngLat: LngLat; }; export type GeolocateEvent = IMapEvent; export type GeolocateResultEvent = GeolocateEvent & GeolocationPosition; export type GeolocateErrorEvent = GeolocateEvent & GeolocationPositionError; ================================================ FILE: modules/main/src/mapbox-legacy/types/internal.ts ================================================ // Internal types import type {Map, LngLat, PaddingOptions, Point} from 'mapbox-gl'; export type { AnySourceImpl as AnySourceImplementation, GeoJSONSource as GeoJSONSourceImplementation, ImageSource as ImageSourceImplemtation, CanvasSource as CanvasSourceImplemtation, VectorSourceImpl as VectorSourceImplementation, RasterSourceImpl as RasterSourceImplementation, VideoSource as VideoSourceImplementation } from 'mapbox-gl'; /** * Stub for mapbox's Transform class * https://github.com/mapbox/mapbox-gl-js/blob/main/src/geo/transform.js */ export type Transform = { width: number; height: number; center: LngLat; zoom: number; bearing: number; pitch: number; padding: PaddingOptions; elevation: any; pixelsToGLUnits: [number, number]; cameraElevationReference: 'ground' | 'sea'; clone: () => Transform; resize: (width: number, height: number) => void; isPaddingEqual: (value: PaddingOptions) => boolean; getBounds: () => any; locationPoint: (lngLat: LngLat) => Point; pointLocation: (p: Point) => LngLat; // Mapbox only getProjection?: () => any; setProjection?: (projection: any) => void; }; export type MapInstanceInternal = Map & { transform: Transform; _render: Function; _renderTaskQueue: { run: Function; }; }; ================================================ FILE: modules/main/src/mapbox-legacy/types/lib.ts ================================================ import type { Map as MapInstance, MapboxOptions as MapOptions, Marker as MarkerInstance, MarkerOptions, Popup as PopupInstance, PopupOptions, AttributionControl as AttributionControlInstance, FullscreenControl as FullscreenControlInstance, FullscreenControlOptions, GeolocateControl as GeolocateControlInstance, NavigationControl as NavigationControlInstance, ScaleControl as ScaleControlInstance } from 'mapbox-gl'; type AttributionControlOptions = ConstructorParameters[0]; type GeolocateControlOptions = ConstructorParameters[0]; type NavigationControlOptions = ConstructorParameters[0]; type ScaleControlOptions = ConstructorParameters[0]; export type {IControl, CustomLayerInterface} from 'mapbox-gl'; export type { MapInstance, MapOptions, MarkerInstance, MarkerOptions, PopupInstance, PopupOptions, AttributionControlInstance, AttributionControlOptions, FullscreenControlInstance, FullscreenControlOptions, GeolocateControlInstance, GeolocateControlOptions, NavigationControlInstance, NavigationControlOptions, ScaleControlInstance, ScaleControlOptions }; export type ControlPosition = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'; /** * A user-facing type that represents the minimal intersection between Mapbox and Maplibre * User provided `mapLib` is supposed to implement this interface * Only loosely typed for compatibility */ export interface MapLib { supported?: (options: any) => boolean; Map: {new (options: MapOptions): MapInstance}; Marker: {new (options: MarkerOptions): MarkerInstance}; Popup: {new (options: PopupOptions): PopupInstance}; AttributionControl: {new (options: AttributionControlOptions): AttributionControlInstance}; FullscreenControl: {new (options: FullscreenControlOptions): FullscreenControlInstance}; GeolocateControl: {new (options: GeolocateControlOptions): GeolocateControlInstance}; NavigationControl: {new (options: NavigationControlOptions): NavigationControlInstance}; ScaleControl: {new (options: ScaleControlOptions): ScaleControlInstance}; } ================================================ FILE: modules/main/src/mapbox-legacy/types/style-spec.ts ================================================ /* * Mapbox Style Specification types */ export type { // Layers AnyLayer as LayerSpecification, BackgroundLayer as BackgroundLayerSpecification, SkyLayer as SkyLayerSpecification, CircleLayer as CircleLayerSpecification, FillLayer as FillLayerSpecification, FillExtrusionLayer as FillExtrusionLayerSpecification, HeatmapLayer as HeatmapLayerSpecification, HillshadeLayer as HillshadeLayerSpecification, LineLayer as LineLayerSpecification, RasterLayer as RasterLayerSpecification, SymbolLayer as SymbolLayerSpecification, // Sources AnySourceData as SourceSpecification, CanvasSourceRaw as CanvasSourceSpecification, GeoJSONSourceRaw as GeoJSONSourceSpecification, VideoSourceRaw as VideoSourceSpecification, ImageSourceRaw as ImageSourceSpecification, VectorSource as VectorSourceSpecification, RasterSource as RasterSourceSpecification, RasterDemSource as RasterDemSourceSpecification, // Style Style as StyleSpecification, Light as LightSpecification, Fog as FogSpecification, TerrainSpecification, Projection as ProjectionSpecification } from 'mapbox-gl'; ================================================ FILE: modules/main/src/mapbox-legacy/utils/apply-react-style.ts ================================================ import * as React from 'react'; // This is a simplified version of // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { if (!element || !styles) { return; } const style = element.style; for (const key in styles) { const value = styles[key]; if (Number.isFinite(value) && !unitlessNumber.test(key)) { style[key] = `${value}px`; } else { style[key] = value; } } } ================================================ FILE: modules/main/src/mapbox-legacy/utils/assert.ts ================================================ export default function assert(condition: any, message: string) { if (!condition) { throw new Error(message); } } ================================================ FILE: modules/main/src/mapbox-legacy/utils/deep-equal.ts ================================================ import type {PointLike} from '../types/common'; /** * Compare two points * @param a * @param b * @returns true if the points are equal */ export function arePointsEqual(a?: PointLike, b?: PointLike): boolean { const ax = Array.isArray(a) ? a[0] : a ? a.x : 0; const ay = Array.isArray(a) ? a[1] : a ? a.y : 0; const bx = Array.isArray(b) ? b[0] : b ? b.x : 0; const by = Array.isArray(b) ? b[1] : b ? b.y : 0; return ax === bx && ay === by; } /* eslint-disable complexity */ /** * Compare any two objects * @param a * @param b * @returns true if the objects are deep equal */ export function deepEqual(a: any, b: any): boolean { if (a === b) { return true; } if (!a || !b) { return false; } if (Array.isArray(a)) { if (!Array.isArray(b) || a.length !== b.length) { return false; } for (let i = 0; i < a.length; i++) { if (!deepEqual(a[i], b[i])) { return false; } } return true; } else if (Array.isArray(b)) { return false; } if (typeof a === 'object' && typeof b === 'object') { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) { return false; } for (const key of aKeys) { if (!b.hasOwnProperty(key)) { return false; } if (!deepEqual(a[key], b[key])) { return false; } } return true; } return false; } ================================================ FILE: modules/main/src/mapbox-legacy/utils/set-globals.ts ================================================ export type GlobalSettings = { /** The map's default API URL for requesting tiles, styles, sprites, and glyphs. */ baseApiUrl?: string; /** The maximum number of images (raster tiles, sprites, icons) to load in parallel. * @default 16 */ maxParallelImageRequests?: number; /** The map's RTL text plugin. Necessary for supporting the Arabic and Hebrew languages, which are written right-to-left. */ RTLTextPlugin?: string | false; /** Provides an interface for external module bundlers such as Webpack or Rollup to package mapbox-gl's WebWorker into a separate class and integrate it with the library. Takes precedence over `workerUrl`. */ workerClass?: any; /** The number of web workers instantiated on a page with mapbox-gl maps. * @default 2 */ workerCount?: number; /** Provides an interface for loading mapbox-gl's WebWorker bundle from a self-hosted URL. * This is useful if your site needs to operate in a strict CSP (Content Security Policy) environment * wherein you are not allowed to load JavaScript code from a Blob URL, which is default behavior. */ workerUrl?: string; }; const globalSettings = [ 'baseApiUrl', 'maxParallelImageRequests', 'workerClass', 'workerCount', 'workerUrl' ] as const; export default function setGlobals(mapLib: any, props: GlobalSettings) { for (const key of globalSettings) { if (key in props) { mapLib[key] = props[key]; } } const { RTLTextPlugin = 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js' } = props; if ( RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === 'unavailable' ) { mapLib.setRTLTextPlugin( RTLTextPlugin, (error?: Error) => { if (error) { // eslint-disable-next-line console.error(error); } }, true ); } } ================================================ FILE: modules/main/src/mapbox-legacy/utils/style-utils.ts ================================================ import {ImmutableLike} from '../types/common'; import {StyleSpecification} from '../types/style-spec'; const refProps = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout']; // Prepare a map style object for diffing // If immutable - convert to plain object // Work around some issues in older styles that would fail Mapbox's diffing export function normalizeStyle( style: string | StyleSpecification | ImmutableLike ): string | StyleSpecification { if (!style) { return null; } if (typeof style === 'string') { return style; } if ('toJS' in style) { style = style.toJS(); } if (!style.layers) { return style; } const layerIndex = {}; for (const layer of style.layers) { layerIndex[layer.id] = layer; } const layers = style.layers.map(layer => { let normalizedLayer: typeof layer = null; if ('interactive' in layer) { normalizedLayer = Object.assign({}, layer); // Breaks style diffing :( // @ts-ignore legacy field not typed delete normalizedLayer.interactive; } // Style diffing doesn't work with refs so expand them out manually before diffing. // @ts-ignore legacy field not typed const layerRef = layerIndex[layer.ref]; if (layerRef) { normalizedLayer = normalizedLayer || Object.assign({}, layer); // @ts-ignore delete normalizedLayer.ref; // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/deref.js for (const propName of refProps) { if (propName in layerRef) { normalizedLayer[propName] = layerRef[propName]; } } } return normalizedLayer || layer; }); // Do not mutate the style object provided by the user return {...style, layers}; } ================================================ FILE: modules/main/src/mapbox-legacy/utils/transform.ts ================================================ import type {MapboxProps} from '../mapbox/mapbox'; import type {Transform} from '../types/internal'; import type {ViewState} from '../types/common'; import {deepEqual} from './deep-equal'; /** * Make a copy of a transform * @param tr */ export function cloneTransform(tr: Transform): Transform { const newTransform = tr.clone(); // Work around mapbox bug - this value is not assigned in clone(), only in resize() newTransform.pixelsToGLUnits = tr.pixelsToGLUnits; return newTransform; } /** * Copy projection from one transform to another. This only applies to mapbox-gl transforms * @param src the transform to copy projection settings from * @param dest to transform to copy projection settings to */ export function syncProjection(src: Transform, dest: Transform): void { if (!src.getProjection) { return; } const srcProjection = src.getProjection(); const destProjection = dest.getProjection(); if (!deepEqual(srcProjection, destProjection)) { dest.setProjection(srcProjection); } } /** * Capture a transform's current state * @param transform * @returns descriptor of the view state */ export function transformToViewState(tr: Transform): ViewState { return { longitude: tr.center.lng, latitude: tr.center.lat, zoom: tr.zoom, pitch: tr.pitch, bearing: tr.bearing, padding: tr.padding }; } /* eslint-disable complexity */ /** * Mutate a transform to match the given view state * @param transform * @param viewState * @returns true if the transform has changed */ export function applyViewStateToTransform(tr: Transform, props: MapboxProps): boolean { const v: Partial = props.viewState || props; let changed = false; if ('zoom' in v) { const zoom = tr.zoom; tr.zoom = v.zoom; changed = changed || zoom !== tr.zoom; } if ('bearing' in v) { const bearing = tr.bearing; tr.bearing = v.bearing; changed = changed || bearing !== tr.bearing; } if ('pitch' in v) { const pitch = tr.pitch; tr.pitch = v.pitch; changed = changed || pitch !== tr.pitch; } if (v.padding && !tr.isPaddingEqual(v.padding)) { changed = true; tr.padding = v.padding; } if ('longitude' in v && 'latitude' in v) { const center = tr.center; // @ts-ignore tr.center = new center.constructor(v.longitude, v.latitude); changed = changed || center !== tr.center; } return changed; } ================================================ FILE: modules/main/src/mapbox-legacy/utils/use-isomorphic-layout-effect.ts ================================================ // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts // useLayoutEffect but does not trigger warning in server-side rendering import {useEffect, useLayoutEffect} from 'react'; const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; export default useIsomorphicLayoutEffect; ================================================ FILE: modules/main/src/mapbox.ts ================================================ export * from '@vis.gl/react-mapbox'; export {Map as default} from '@vis.gl/react-mapbox'; ================================================ FILE: modules/main/src/maplibre.ts ================================================ export * from '@vis.gl/react-maplibre'; export {Map as default} from '@vis.gl/react-maplibre'; ================================================ FILE: modules/main/test/components/controls.spec.jsx ================================================ import { Map, AttributionControl, FullscreenControl, GeolocateControl, NavigationControl, ScaleControl } from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Controls', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-attrib'), 'Rendered '); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-fullscreen'), 'Rendered '); const geolocateControlRef = {current: null}; root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-geolocate'), 'Rendered '); t.ok(geolocateControlRef.current, 'GeolocateControl created'); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-zoom-in'), 'Rendered '); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-scale'), 'Rendered '); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/components/index.js ================================================ import './map.spec'; import './controls.spec'; import './source.spec'; import './layer.spec'; import './marker.spec'; import './popup.spec'; import './use-map.spec'; ================================================ FILE: modules/main/test/components/layer.spec.jsx ================================================ import {Map, Source, Layer} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const pointLayer = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; const pointLayer2 = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#000000' }, layout: { visibility: 'none' } }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); const layer = mapRef.current.getLayer('my-layer'); t.ok(layer, 'Layer is added'); root.render( ); await sleep(1); t.is(layer.visibility, 'none', 'Layer is updated'); root.render( ); await sleep(50); t.ok(mapRef.current.getLayer('my-layer'), 'Layer is added after style change'); root.render(); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); t.notOk(mapRef.current.getLayer('my-layer'), 'Layer is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/components/map.spec.jsx ================================================ /* global setTimeout */ import {Map} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Map', async t => { t.ok(Map, 'Map is defined'); const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let onloadCalled = 0; const onLoad = () => onloadCalled++; root.render( ); await waitForMapLoad(mapRef); t.ok(mapRef.current, 'Map is created'); t.is(mapRef.current.getCenter().lng, -100, 'longitude is set'); t.is(mapRef.current.getCenter().lat, 40, 'latitude is set'); t.is(mapRef.current.getZoom(), 4, 'zoom is set'); root.render( ); await sleep(1); t.is(mapRef.current.getCenter().lng, -122, 'longitude is updated'); t.is(mapRef.current.getCenter().lat, 38, 'latitude is updated'); t.is(mapRef.current.getZoom(), 14, 'zoom is updated'); t.is(onloadCalled, 1, 'onLoad is called'); root.unmount(); t.end(); }); test('Map#uncontrolled', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } let lastCenter; function onRender() { const center = mapRef.current.getCenter(); if (lastCenter) { t.ok(lastCenter.lng > center.lng && lastCenter.lat > center.lat, `animated to ${center}`); } lastCenter = center; } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#controlled#no-update', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender() { const center = mapRef.current.getCenter(); t.ok(center.lng === -100 && center.lat === 40, `map center should match props: ${center}`); } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#controlled#mirror-back', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs) { const center = mapRef.current.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setViewState(e.viewState)} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); test('Map#controlled#delayed-update', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs) { const center = mapRef.current.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setTimeout(() => setViewState(e.viewState))} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); ================================================ FILE: modules/main/test/components/marker.spec.jsx ================================================ import {Map, Marker} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Marker', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const markerRef = {current: null}; const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-marker'), 'Marker is attached to DOM'); t.ok(markerRef.current, 'Marker is created'); const marker = markerRef.current; const offset = marker.getOffset(); const draggable = marker.isDraggable(); const rotation = marker.getRotation(); const pitchAlignment = marker.getPitchAlignment(); const rotationAlignment = marker.getRotationAlignment(); root.render( ); t.is(offset, marker.getOffset(), 'offset did not change deeply'); let callbackType = ''; root.render( (callbackType = 'dragstart')} onDrag={() => (callbackType = 'drag')} onDragEnd={() => (callbackType = 'dragend')} /> ); await sleep(1); t.not(offset, marker.getOffset(), 'offset is updated'); t.not(draggable, marker.isDraggable(), 'draggable is updated'); t.not(rotation, marker.getRotation(), 'rotation is updated'); t.not(pitchAlignment, marker.getPitchAlignment(), 'pitchAlignment is updated'); t.not(rotationAlignment, marker.getRotationAlignment(), 'rotationAlignment is updated'); marker.fire('dragstart'); t.is(callbackType, 'dragstart', 'onDragStart called'); marker.fire('drag'); t.is(callbackType, 'drag', 'onDrag called'); marker.fire('dragend'); t.is(callbackType, 'dragend', 'onDragEnd called'); root.render(); await sleep(1); t.notOk(markerRef.current, 'marker is removed'); root.render(
); await sleep(1); t.ok(rootContainer.querySelector('#marker-content'), 'content is rendered'); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/components/popup.spec.jsx ================================================ import {Map, Popup} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Popup', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; const popupRef = {current: null}; root.render( You are here ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-popup'), 'Popup is attached to DOM'); t.ok(popupRef.current, 'Popup is created'); const popup = popupRef.current; const {anchor, offset, maxWidth} = popup.options; root.render( ); await sleep(1); t.is(offset, popup.options.offset, 'offset did not change deeply'); t.ok(rootContainer.querySelector('#popup-content'), 'content is rendered'); root.render( ); await sleep(1); t.not(offset, popup.options.offset, 'offset is updated'); t.not(anchor, popup.options.anchor, 'anchor is updated'); t.not(maxWidth, popup.options.maxWidth, 'maxWidth is updated'); root.render( ); await sleep(1); t.is(popup.options.className, 'classA', 'className is updated'); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/components/source.spec.jsx ================================================ import {Map, Source} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const geoJSON2 = { type: 'Point', coordinates: [1, 1] }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(mapRef.current.getSource('my-data'), 'Source is added'); root.render( ); await sleep(50); t.ok(mapRef.current.getSource('my-data'), 'Source is added after style change'); root.render( ); await sleep(1); const sourceData = await mapRef.current.getSource('my-data')?._data; t.deepEqual(sourceData, geoJSON2, 'Source is updated'); root.render(); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/components/use-map.spec.jsx ================================================ import {Map, MapProvider, useMap} from 'react-map-gl/mapbox-legacy'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('useMap', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let maps = null; function TestControl() { maps = useMap(); return null; } root.render( ); await waitForMapLoad(mapRef); t.ok(maps.mapA, 'Context has mapA'); t.ok(maps.mapB, 'Context has mapB'); root.render( ); await sleep(50); t.ok(maps.mapA, 'Context has mapA'); t.notOk(maps.mapB, 'mapB is removed'); root.render( ); await sleep(50); t.notOk(maps.mapA, 'mapA is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/main/test/utils/apply-react-style.spec.js ================================================ import test from 'tape-promise/tape'; import {applyReactStyle} from 'react-map-gl/mapbox-legacy/utils/apply-react-style'; test('applyReactStyle', t => { /* global document */ if (typeof document === 'undefined') { t.end(); return; } const div = document.createElement('div'); t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); t.is(div.style.height, '24px', 'appended px to numeric value'); t.is(div.style.lineHeight, '2', 'unitless numeric property'); t.is(div.style.zIndex, '1', 'unitless numeric property'); t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); t.end(); }); ================================================ FILE: modules/main/test/utils/deep-equal.spec.js ================================================ import test from 'tape-promise/tape'; import {deepEqual, arePointsEqual} from 'react-map-gl/mapbox-legacy/utils/deep-equal'; test('deepEqual', t => { const testCases = [ { a: null, b: null, result: true }, { a: undefined, b: 0, result: false }, { a: [1, 2, 3], b: [1, 2, 3], result: true }, { a: [1, 2], b: [1, 2, 3], result: false }, { a: [1, 2], b: {0: 1, 1: 2}, result: false }, { a: {x: 0, y: 0, offset: [1, -1]}, b: {x: 0, y: 0, offset: [1, -1]}, result: true }, { a: {x: 0, y: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false }, { a: {x: 0, y: 0, z: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false } ]; for (const {a, b, result} of testCases) { t.is(deepEqual(a, b), result, `${JSON.stringify(a)} vs ${JSON.stringify(b)}`); if (a !== b) { t.is(deepEqual(b, a), result, `${JSON.stringify(b)} vs ${JSON.stringify(a)}`); } } t.end(); }); test('arePointsEqual', t => { const testCases = [ { a: undefined, b: undefined, result: true }, { a: undefined, b: [0, 0], result: true }, { a: undefined, b: [0, 1], result: false }, { a: undefined, b: [1, 0], result: false }, { a: {x: 1, y: 1}, b: [1, 1], result: true } ]; for (const {a, b, result} of testCases) { t.is(arePointsEqual(a, b), result, `${JSON.stringify(a)}, ${JSON.stringify(b)}`); if (a !== b) { t.is(arePointsEqual(b, a), result, `${JSON.stringify(b)}, ${JSON.stringify(a)}`); } } t.end(); }); ================================================ FILE: modules/main/test/utils/index.js ================================================ import './deep-equal.spec'; import './transform.spec'; import './style-utils.spec'; import './apply-react-style.spec'; ================================================ FILE: modules/main/test/utils/mapbox-gl-mock/edge_insets.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/edge_insets.js import Point from '@mapbox/point-geometry'; import {clamp, number} from './util.js'; class EdgeInsets { constructor(top = 0, bottom = 0, left = 0, right = 0) { if ( isNaN(top) || top < 0 || isNaN(bottom) || bottom < 0 || isNaN(left) || left < 0 || isNaN(right) || right < 0 ) { throw new Error( 'Invalid value for edge-insets, top, bottom, left and right must all be numbers' ); } this.top = top; this.bottom = bottom; this.left = left; this.right = right; } interpolate(start, target, t) { if (target.top != null && start.top != null) this.top = number(start.top, target.top, t); if (target.bottom != null && start.bottom != null) this.bottom = number(start.bottom, target.bottom, t); if (target.left != null && start.left != null) this.left = number(start.left, target.left, t); if (target.right != null && start.right != null) this.right = number(start.right, target.right, t); return this; } getCenter(width, height) { // Clamp insets so they never overflow width/height and always calculate a valid center const x = clamp((this.left + width - this.right) / 2, 0, width); const y = clamp((this.top + height - this.bottom) / 2, 0, height); return new Point(x, y); } equals(other) { return ( this.top === other.top && this.bottom === other.bottom && this.left === other.left && this.right === other.right ); } clone() { return new EdgeInsets(this.top, this.bottom, this.left, this.right); } toJSON() { return { top: this.top, bottom: this.bottom, left: this.left, right: this.right }; } } export default EdgeInsets; ================================================ FILE: modules/main/test/utils/mapbox-gl-mock/lng_lat.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/lng_lat.js import {wrap} from './util.js'; import LngLatBounds from './lng_lat_bounds.js'; export const earthRadius = 6371008.8; class LngLat { lng; lat; constructor(lng, lat) { if (isNaN(lng) || isNaN(lat)) { throw new Error(`Invalid LngLat object: (${lng}, ${lat})`); } this.lng = Number(lng); this.lat = Number(lat); if (this.lat > 90 || this.lat < -90) { throw new Error('Invalid LngLat latitude value: must be between -90 and 90'); } } wrap() { return new LngLat(wrap(this.lng, -180, 180), this.lat); } toArray() { return [this.lng, this.lat]; } toString() { return `LngLat(${this.lng}, ${this.lat})`; } distanceTo(lngLat) { const rad = Math.PI / 180; const lat1 = this.lat * rad; const lat2 = lngLat.lat * rad; const a = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos((lngLat.lng - this.lng) * rad); const maxMeters = earthRadius * Math.acos(Math.min(a, 1)); return maxMeters; } toBounds(radius = 0) { const earthCircumferenceInMetersAtEquator = 40075017; const latAccuracy = (360 * radius) / earthCircumferenceInMetersAtEquator; const lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); return new LngLatBounds( new LngLat(this.lng - lngAccuracy, this.lat - latAccuracy), new LngLat(this.lng + lngAccuracy, this.lat + latAccuracy) ); } static convert(input) { if (input instanceof LngLat) { return input; } if (Array.isArray(input) && (input.length === 2 || input.length === 3)) { return new LngLat(Number(input[0]), Number(input[1])); } if (!Array.isArray(input) && typeof input === 'object' && input !== null) { return new LngLat( // flow can't refine this to have one of lng or lat, so we have to cast to any Number('lng' in input ? input.lng : input.lon), Number(input.lat) ); } throw new Error( '`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, an object {lon: , lat: }, or an array of [, ]' ); } } export default LngLat; ================================================ FILE: modules/main/test/utils/mapbox-gl-mock/lng_lat_bounds.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/lng_lat_bounds.js import LngLat from './lng_lat.js'; class LngLatBounds { _ne; _sw; // This constructor is too flexible to type. It should not be so flexible. constructor(sw, ne) { if (!sw) { // noop } else if (ne) { this.setSouthWest(sw).setNorthEast(ne); } else if (sw.length === 4) { this.setSouthWest([sw[0], sw[1]]).setNorthEast([sw[2], sw[3]]); } else { this.setSouthWest(sw[0]).setNorthEast(sw[1]); } } setNorthEast(ne) { this._ne = ne instanceof LngLat ? new LngLat(ne.lng, ne.lat) : LngLat.convert(ne); return this; } setSouthWest(sw) { this._sw = sw instanceof LngLat ? new LngLat(sw.lng, sw.lat) : LngLat.convert(sw); return this; } extend(obj) { const sw = this._sw; const ne = this._ne; let ne2; let sw2; if (obj instanceof LngLat) { sw2 = obj; ne2 = obj; } else if (obj instanceof LngLatBounds) { sw2 = obj._sw; ne2 = obj._ne; if (!sw2 || !ne2) return this; } else { if (Array.isArray(obj)) { if (obj.length === 4 || obj.every(Array.isArray)) { const lngLatBoundsObj = obj; return this.extend(LngLatBounds.convert(lngLatBoundsObj)); } const lngLatObj = obj; return this.extend(LngLat.convert(lngLatObj)); } return this; } if (!sw && !ne) { this._sw = new LngLat(sw2.lng, sw2.lat); this._ne = new LngLat(ne2.lng, ne2.lat); } else { sw.lng = Math.min(sw2.lng, sw.lng); sw.lat = Math.min(sw2.lat, sw.lat); ne.lng = Math.max(ne2.lng, ne.lng); ne.lat = Math.max(ne2.lat, ne.lat); } return this; } getCenter() { return new LngLat((this._sw.lng + this._ne.lng) / 2, (this._sw.lat + this._ne.lat) / 2); } getSouthWest() { return this._sw; } getNorthEast() { return this._ne; } getNorthWest() { return new LngLat(this.getWest(), this.getNorth()); } getSouthEast() { return new LngLat(this.getEast(), this.getSouth()); } getWest() { return this._sw.lng; } getSouth() { return this._sw.lat; } getEast() { return this._ne.lng; } getNorth() { return this._ne.lat; } toArray() { return [this._sw.toArray(), this._ne.toArray()]; } toString() { return `LngLatBounds(${this._sw.toString()}, ${this._ne.toString()})`; } isEmpty() { return !(this._sw && this._ne); } contains(lnglat) { const {lng, lat} = LngLat.convert(lnglat); const containsLatitude = this._sw.lat <= lat && lat <= this._ne.lat; let containsLongitude = this._sw.lng <= lng && lng <= this._ne.lng; if (this._sw.lng > this._ne.lng) { // wrapped coordinates containsLongitude = this._sw.lng >= lng && lng >= this._ne.lng; } return containsLatitude && containsLongitude; } static convert(input) { if (!input || input instanceof LngLatBounds) return input; return new LngLatBounds(input); } } export default LngLatBounds; ================================================ FILE: modules/main/test/utils/mapbox-gl-mock/transform.js ================================================ import {wrap, clamp} from './util'; import LngLat from './lng_lat'; import EdgeInsets from './edge_insets'; export default class Transform { constructor() { this.minZoom = 0; this.maxZoom = 22; this.minPitch = 0; this.maxPitch = 60; this.minLat = -85.051129; this.maxLat = 85.051129; this.minLng = -180; this.maxLng = 180; this.width = 1; this.height = 1; this._center = new LngLat(0, 0); this._zoom = 0; this.angle = 0; this._pitch = 0; this._edgeInsets = new EdgeInsets(); } get bearing() { return wrap(this.rotation, -180, 180); } set bearing(bearing) { this.rotation = bearing; } get rotation() { return (-this.angle / Math.PI) * 180; } set rotation(rotation) { const b = (-rotation * Math.PI) / 180; if (this.angle === b) return; this.angle = b; } get pitch() { return (this._pitch / Math.PI) * 180; } set pitch(pitch) { const p = (clamp(pitch, this.minPitch, this.maxPitch) / 180) * Math.PI; if (this._pitch === p) return; this._pitch = p; } get zoom() { return this._zoom; } set zoom(zoom) { const z = Math.min(Math.max(zoom, this.minZoom), this.maxZoom); if (this._zoom === z) return; this._zoom = z; } get center() { return this._center; } set center(center) { if (center.lat === this._center.lat && center.lng === this._center.lng) return; this._center = center; } get padding() { return this._edgeInsets.toJSON(); } set padding(padding) { if (this._edgeInsets.equals(padding)) return; // Update edge-insets inplace this._edgeInsets.interpolate(this._edgeInsets, padding, 1); } clone() { const that = new Transform(); that.center = this.center; that.zoom = this.zoom; that.bearing = this.bearing; that.pitch = this.pitch; that.padding = this.padding; return that; } isPaddingEqual(padding) { return this._edgeInsets.equals(padding); } } ================================================ FILE: modules/main/test/utils/mapbox-gl-mock/util.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/util/util.js export function clamp(n, min, max) { return Math.min(max, Math.max(min, n)); } export function wrap(n, min, max) { const d = max - min; const w = ((((n - min) % d) + d) % d) + min; return w === min ? max : w; } export function extend(dest, ...sources) { for (const src of sources) { for (const k in src) { dest[k] = src[k]; } } return dest; } export function number(a, b, t) { return a * (1 - t) + b * t; } ================================================ FILE: modules/main/test/utils/style-utils.spec.js ================================================ import test from 'tape-promise/tape'; import {normalizeStyle} from 'react-map-gl/mapbox-legacy/utils/style-utils'; const testStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 }, interactive: true }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20, interactive: true }, { id: 'park-2', ref: 'park', paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', ref: 'road', minzoom: 10, maxzoom: 12, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; const expectedStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 } }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20 }, { id: 'park-2', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', minzoom: 5, maxzoom: 20, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; test('normalizeStyle', t => { // Make sure the style is not mutated freezeRecursive(testStyle); t.is(normalizeStyle(null), null, 'Handles null'); t.is( normalizeStyle('mapbox://styles/mapbox/light-v9'), 'mapbox://styles/mapbox/light-v9', 'Handles url string' ); let result = normalizeStyle(testStyle); t.notEqual(result, testStyle, 'style is not mutated'); t.deepEqual(result, expectedStyle, 'plain object style is normalized'); // Immutable-like object result = normalizeStyle({toJS: () => testStyle}); t.deepEqual(result, expectedStyle, 'immutable style is normalized'); t.end(); }); function freezeRecursive(obj) { if (!obj) return; if (typeof obj === 'object') { if (Array.isArray(obj)) { for (const el of obj) { freezeRecursive(el); } } else { for (const key in obj) { freezeRecursive(obj[key]); } } Object.freeze(obj); } } ================================================ FILE: modules/main/test/utils/test-utils.jsx ================================================ /* global setTimeout */ export function sleep(milliseconds) { return new Promise(resolve => setTimeout(resolve, milliseconds)); } export function waitForMapLoad(mapRef) { return new Promise(resolve => { const check = () => { if (mapRef.current && mapRef.current.getMap().isStyleLoaded()) { resolve(); } else { setTimeout(check, 50); } }; check(); }); } ================================================ FILE: modules/main/test/utils/transform.spec.js ================================================ import test from 'tape-promise/tape'; import { transformToViewState, applyViewStateToTransform } from 'react-map-gl/mapbox-legacy/utils/transform'; import Transform from './mapbox-gl-mock/transform'; test('applyViewStateToTransform', t => { const tr = new Transform(); let changed = applyViewStateToTransform(tr, {}); t.notOk(changed, 'empty view state'); changed = applyViewStateToTransform(tr, {longitude: -10, latitude: 5}); t.ok(changed, 'center changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 0, pitch: 0, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0} }, 'view state is correct' ); changed = applyViewStateToTransform(tr, {zoom: -1}); t.notOk(changed, 'zoom is clamped'); changed = applyViewStateToTransform(tr, {zoom: 10}); t.ok(changed, 'zoom changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 0, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0} }, 'view state is correct' ); changed = applyViewStateToTransform(tr, {pitch: 30}); t.ok(changed, 'pitch changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0} }, 'view state is correct' ); changed = applyViewStateToTransform(tr, {bearing: 270}); t.ok(changed, 'bearing changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: -90, padding: {left: 0, right: 0, top: 0, bottom: 0} }, 'view state is correct' ); changed = applyViewStateToTransform(tr, {padding: {left: 10, right: 10, top: 10, bottom: 10}}); t.ok(changed, 'padding changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: -90, padding: {left: 10, right: 10, top: 10, bottom: 10} }, 'view state is correct' ); changed = applyViewStateToTransform(tr, {viewState: {pitch: 30}}); t.notOk(changed, 'nothing changed'); applyViewStateToTransform(tr, {longitude: 0, latitude: 0, zoom: 0}); changed = applyViewStateToTransform(tr, {longitude: 12, latitude: 34, zoom: 15}); t.ok(changed, 'center and zoom changed'); t.equal(tr.zoom, 15, 'zoom is correct'); t.equal(tr.center.lat, 34, 'center latitude is correct'); t.end(); }); ================================================ FILE: modules/main/tsconfig.json ================================================ { "extends": "../../tsconfig.json", "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { "composite": true, "rootDir": "src", "outDir": "dist" }, "references": [ {"path": "../react-mapbox"}, {"path": "../react-maplibre"} ] } ================================================ FILE: modules/react-mapbox/package.json ================================================ { "name": "@vis.gl/react-mapbox", "description": "React components for Mapbox GL JS", "version": "8.1.0-alpha.2", "keywords": [ "mapbox", "mapbox-gl", "react", "react mapbox" ], "repository": { "type": "git", "url": "https://github.com/visgl/react-map-gl.git" }, "license": "MIT", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs", "module": "dist/index.js", "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs", "types": "./dist/index.d.ts" } }, "files": [ "src", "dist", "README.md" ], "devDependencies": { "mapbox-gl": "^3.9.0" }, "peerDependencies": { "mapbox-gl": ">=3.5.0", "react": ">=16.3.0", "react-dom": ">=16.3.0" }, "peerDependenciesMeta": { "mapbox-gl": { "optional": true } } } ================================================ FILE: modules/react-mapbox/src/components/attribution-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, AttributionControlOptions} from '../types/lib'; export type AttributionControlProps = AttributionControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _AttributionControl(props: AttributionControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const AttributionControl = memo(_AttributionControl); ================================================ FILE: modules/react-mapbox/src/components/fullscreen-control.ts ================================================ /* global document */ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, FullscreenControlOptions} from '../types/lib'; export type FullscreenControlProps = Omit & { /** Id of the DOM element which should be made full screen. By default, the map container * element will be made full screen. */ containerId?: string; /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _FullscreenControl(props: FullscreenControlProps) { const ctrl = useControl( ({mapLib}) => new mapLib.FullscreenControl({ container: props.containerId && document.getElementById(props.containerId) }), {position: props.position} ); useEffect(() => { applyReactStyle(ctrl._controlContainer, props.style); }, [props.style]); return null; } export const FullscreenControl = memo(_FullscreenControl); ================================================ FILE: modules/react-mapbox/src/components/geolocate-control.ts ================================================ import * as React from 'react'; import {useImperativeHandle, useRef, useEffect, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type { ControlPosition, GeolocateControlInstance, GeolocateControlOptions } from '../types/lib'; import type {GeolocateEvent, GeolocateResultEvent, GeolocateErrorEvent} from '../types/events'; export type GeolocateControlProps = GeolocateControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; /** Called on each Geolocation API position update that returned as success. */ onGeolocate?: (e: GeolocateResultEvent) => void; /** Called on each Geolocation API position update that returned as an error. */ onError?: (e: GeolocateErrorEvent) => void; /** Called on each Geolocation API position update that returned as success but user position * is out of map `maxBounds`. */ onOutOfMaxBounds?: (e: GeolocateResultEvent) => void; /** Called when the GeolocateControl changes to the active lock state. */ onTrackUserLocationStart?: (e: GeolocateEvent) => void; /** Called when the GeolocateControl changes to the background state. */ onTrackUserLocationEnd?: (e: GeolocateEvent) => void; }; function _GeolocateControl(props: GeolocateControlProps, ref: React.Ref) { const thisRef = useRef({props}); const ctrl = useControl( ({mapLib}) => { const gc = new mapLib.GeolocateControl(props); // Hack: fix GeolocateControl reuse // When using React strict mode, the component is mounted twice. // GeolocateControl's UI creation is asynchronous. Removing and adding it back causes the UI to be initialized twice. const setupUI = gc._setupUI.bind(gc); gc._setupUI = args => { if (!gc._container.hasChildNodes()) { setupUI(args); } }; gc.on('geolocate', e => { thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent); }); gc.on('error', e => { thisRef.current.props.onError?.(e as GeolocateErrorEvent); }); gc.on('outofmaxbounds', e => { thisRef.current.props.onOutOfMaxBounds?.(e as GeolocateResultEvent); }); gc.on('trackuserlocationstart', e => { thisRef.current.props.onTrackUserLocationStart?.(e as GeolocateEvent); }); gc.on('trackuserlocationend', e => { thisRef.current.props.onTrackUserLocationEnd?.(e as GeolocateEvent); }); return gc; }, {position: props.position} ); thisRef.current.props = props; useImperativeHandle(ref, () => ctrl, []); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const GeolocateControl = memo(forwardRef(_GeolocateControl)); ================================================ FILE: modules/react-mapbox/src/components/layer.ts ================================================ import {useContext, useEffect, useMemo, useState, useRef} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type {MapInstance, CustomLayerInterface} from '../types/lib'; import type {LayerSpecification} from '../types/style-spec'; // Omiting property from a union type, see // https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230 type OptionalId = T extends {id: string} ? Omit & {id?: string} : T; type OptionalSource = T extends {source: string} ? Omit & {source?: string} : T; export type LayerProps = (OptionalSource> | CustomLayerInterface) & { /** If set, the layer will be inserted before the specified layer */ beforeId?: string; }; /* eslint-disable complexity, max-statements */ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: LayerProps) { assert(props.id === prevProps.id, 'layer id changed'); assert(props.type === prevProps.type, 'layer type changed'); if (props.type === 'custom' || prevProps.type === 'custom') { return; } // @ts-ignore filter does not exist in some Layer types const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props; if (beforeId !== prevProps.beforeId) { map.moveLayer(id, beforeId); } if (layout !== prevProps.layout) { const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { map.setLayoutProperty(id, key as any, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { map.setLayoutProperty(id, key as any, undefined); } } } if (paint !== prevProps.paint) { const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { map.setPaintProperty(id, key as any, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { map.setPaintProperty(id, key as any, undefined); } } } // @ts-ignore filter does not exist in some Layer types if (!deepEqual(filter, prevProps.filter)) { map.setFilter(id, filter); } if (minzoom !== prevProps.minzoom || maxzoom !== prevProps.maxzoom) { map.setLayerZoomRange(id, minzoom, maxzoom); } } function createLayer(map: MapInstance, id: string, props: LayerProps) { // @ts-ignore if (map.style && map.style._loaded && (!('source' in props) || map.getSource(props.source))) { const options: LayerProps = {...props, id}; delete options.beforeId; // @ts-ignore map.addLayer(options, props.beforeId); } } /* eslint-enable complexity, max-statements */ let layerCounter = 0; export function Layer(props: LayerProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-layer-${layerCounter++}`, []); useEffect(() => { if (map) { const forceUpdate = () => setStyleLoaded(version => version + 1); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getLayer(id)) { map.removeLayer(id); } }; } return undefined; }, [map]); // @ts-ignore const layer = map && map.style && map.getLayer(id); if (layer) { try { updateLayer(map, id, props, propsRef.current); } catch (error) { console.warn(error); // eslint-disable-line } } else { createLayer(map, id, props); } // Store last rendered props propsRef.current = props; return null; } ================================================ FILE: modules/react-mapbox/src/components/map.tsx ================================================ import * as React from 'react'; import {useState, useRef, useEffect, useContext, useMemo, useImperativeHandle} from 'react'; import {MountedMapsContext} from './use-map'; import Mapbox, {MapboxProps} from '../mapbox/mapbox'; import createRef, {MapRef} from '../mapbox/create-ref'; import type {CSSProperties} from 'react'; import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect'; import setGlobals, {GlobalSettings} from '../utils/set-globals'; import type {MapLib, MapOptions} from '../types/lib'; export type MapContextValue = { mapLib: MapLib; map: MapRef; }; export const MapContext = React.createContext(null); type MapInitOptions = Omit< MapOptions, 'style' | 'container' | 'bounds' | 'fitBoundsOptions' | 'center' >; export type MapProps = MapInitOptions & MapboxProps & GlobalSettings & { mapLib?: MapLib | Promise; reuseMaps?: boolean; /** Map container id */ id?: string; /** Map container CSS style */ style?: CSSProperties; children?: any; }; function _Map(props: MapProps, ref: React.Ref) { const mountedMapsContext = useContext(MountedMapsContext); const [mapInstance, setMapInstance] = useState(null); const containerRef = useRef(); const {current: contextValue} = useRef({mapLib: null, map: null}); useEffect(() => { const mapLib = props.mapLib; let isMounted = true; let mapbox: Mapbox; Promise.resolve(mapLib || import('mapbox-gl')) .then((module: MapLib | {default: MapLib}) => { if (!isMounted) { return; } if (!module) { throw new Error('Invalid mapLib'); } const mapboxgl = 'Map' in module ? module : module.default; if (!mapboxgl.Map) { throw new Error('Invalid mapLib'); } setGlobals(mapboxgl, props); if (props.reuseMaps) { mapbox = Mapbox.reuse(props, containerRef.current); } if (!mapbox) { mapbox = new Mapbox(mapboxgl.Map, props, containerRef.current); } contextValue.map = createRef(mapbox); contextValue.mapLib = mapboxgl; setMapInstance(mapbox); mountedMapsContext?.onMapMount(contextValue.map, props.id); }) .catch(error => { const {onError} = props; if (onError) { onError({ type: 'error', target: null, error }); } else { console.error(error); // eslint-disable-line } }); return () => { isMounted = false; if (mapbox) { mountedMapsContext?.onMapUnmount(props.id); if (props.reuseMaps) { mapbox.recycle(); } else { mapbox.destroy(); } } }; }, []); useIsomorphicLayoutEffect(() => { if (mapInstance) { mapInstance.setProps(props); } }); useImperativeHandle(ref, () => contextValue.map, [mapInstance]); const style: CSSProperties = useMemo( () => ({ position: 'relative', width: '100%', height: '100%', ...props.style }), [props.style] ); const CHILD_CONTAINER_STYLE = { height: '100%' }; return (
{mapInstance && (
{props.children}
)}
); } export const Map = React.forwardRef(_Map); ================================================ FILE: modules/react-mapbox/src/components/marker.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance, MarkerInstance, MarkerOptions} from '../types/lib'; import type {MarkerEvent, MarkerDragEvent} from '../types/events'; import {MapContext} from './map'; import {arePointsEqual} from '../utils/deep-equal'; import {compareClassNames} from '../utils/compare-class-names'; export type MarkerProps = MarkerOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; popup?: PopupInstance; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onClick?: (e: MarkerEvent) => void; onDragStart?: (e: MarkerDragEvent) => void; onDrag?: (e: MarkerDragEvent) => void; onDragEnd?: (e: MarkerDragEvent) => void; children?: React.ReactNode; }; /* eslint-disable complexity,max-statements */ export const Marker = memo( forwardRef((props: MarkerProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const thisRef = useRef({props}); const marker: MarkerInstance = useMemo(() => { let hasChildren = false; React.Children.forEach(props.children, el => { if (el) { hasChildren = true; } }); const options = { ...props, element: hasChildren ? document.createElement('div') : null }; const mk = new mapLib.Marker(options); mk.setLngLat([props.longitude, props.latitude]); mk.getElement().addEventListener('click', (e: MouseEvent) => { thisRef.current.props.onClick?.({ type: 'click', target: mk, originalEvent: e }); }); mk.on('dragstart', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragStart?.(evt); }); mk.on('drag', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDrag?.(evt); }); mk.on('dragend', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragEnd?.(evt); }); return mk; }, []); useEffect(() => { marker.addTo(map.getMap()); return () => { marker.remove(); }; }, []); const { longitude, latitude, offset, style, draggable = false, popup = null, rotation = 0, rotationAlignment = 'auto', pitchAlignment = 'auto' } = props; useEffect(() => { applyReactStyle(marker.getElement(), style); }, [style]); useImperativeHandle(ref, () => marker, []); const oldProps = thisRef.current.props; if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) { marker.setLngLat([longitude, latitude]); } if (offset && !arePointsEqual(marker.getOffset(), offset)) { marker.setOffset(offset); } if (marker.isDraggable() !== draggable) { marker.setDraggable(draggable); } if (marker.getRotation() !== rotation) { marker.setRotation(rotation); } if (marker.getRotationAlignment() !== rotationAlignment) { marker.setRotationAlignment(rotationAlignment); } if (marker.getPitchAlignment() !== pitchAlignment) { marker.setPitchAlignment(pitchAlignment); } if (marker.getPopup() !== popup) { marker.setPopup(popup); } const classNameDiff = compareClassNames(oldProps.className, props.className); if (classNameDiff) { for (const c of classNameDiff) { marker.toggleClassName(c); } } thisRef.current.props = props; return createPortal(props.children, marker.getElement()); }) ); ================================================ FILE: modules/react-mapbox/src/components/navigation-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, NavigationControlOptions} from '../types/lib'; export type NavigationControlProps = NavigationControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _NavigationControl(props: NavigationControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const NavigationControl = memo(_NavigationControl); ================================================ FILE: modules/react-mapbox/src/components/popup.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance, PopupOptions} from '../types/lib'; import type {PopupEvent} from '../types/events'; import {MapContext} from './map'; import {deepEqual} from '../utils/deep-equal'; import {compareClassNames} from '../utils/compare-class-names'; export type PopupProps = PopupOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onOpen?: (e: PopupEvent) => void; onClose?: (e: PopupEvent) => void; children?: React.ReactNode; }; /* eslint-disable complexity,max-statements */ export const Popup = memo( forwardRef((props: PopupProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const container = useMemo(() => { return document.createElement('div'); }, []); const thisRef = useRef({props}); const popup: PopupInstance = useMemo(() => { const options = {...props}; const pp = new mapLib.Popup(options); pp.setLngLat([props.longitude, props.latitude]); pp.once('open', e => { thisRef.current.props.onOpen?.(e as PopupEvent); }); return pp; }, []); useEffect(() => { const onClose = e => { thisRef.current.props.onClose?.(e as PopupEvent); }; popup.on('close', onClose); popup.setDOMContent(container).addTo(map.getMap()); return () => { // https://github.com/visgl/react-map-gl/issues/1825 // onClose should not be fired if the popup is removed by unmounting // When using React strict mode, the component is mounted twice. // Firing the onClose callback here would be a false signal to remove the component. popup.off('close', onClose); if (popup.isOpen()) { popup.remove(); } }; }, []); useEffect(() => { applyReactStyle(popup.getElement(), props.style); }, [props.style]); useImperativeHandle(ref, () => popup, []); if (popup.isOpen()) { const oldProps = thisRef.current.props; if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) { popup.setLngLat([props.longitude, props.latitude]); } if (props.offset && !deepEqual(oldProps.offset, props.offset)) { popup.options.anchor = props.anchor; popup.setOffset(props.offset); } if (oldProps.anchor !== props.anchor || oldProps.maxWidth !== props.maxWidth) { popup.setMaxWidth(props.maxWidth); } const classNameDiff = compareClassNames(oldProps.className, props.className); if (classNameDiff) { for (const c of classNameDiff) { popup.toggleClassName(c); } } thisRef.current.props = props; } return createPortal(props.children, container); }) ); ================================================ FILE: modules/react-mapbox/src/components/scale-control.ts ================================================ import * as React from 'react'; import {useEffect, useRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, ScaleControlOptions} from '../types/lib'; export type ScaleControlProps = ScaleControlOptions & { // These props will be further constraint by OptionsT unit?: string; maxWidth?: number; /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _ScaleControl(props: ScaleControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.ScaleControl(props), { position: props.position }); const propsRef = useRef(props); const prevProps = propsRef.current; propsRef.current = props; const {style} = props; if (props.maxWidth !== undefined && props.maxWidth !== prevProps.maxWidth) { ctrl.options.maxWidth = props.maxWidth; } if (props.unit !== undefined && props.unit !== prevProps.unit) { ctrl.setUnit(props.unit); } useEffect(() => { applyReactStyle(ctrl._container, style); }, [style]); return null; } export const ScaleControl = memo(_ScaleControl); ================================================ FILE: modules/react-mapbox/src/components/source.ts ================================================ import * as React from 'react'; import {useContext, useEffect, useMemo, useState, useRef, cloneElement} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type { SourceSpecification, CanvasSourceSpecification, ImageSourceSpecification, VectorSourceSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; import type { GeoJSONSourceImplementation, ImageSourceImplementation, AnySourceImplementation } from '../types/internal'; export type SourceProps = (SourceSpecification | CanvasSourceSpecification) & { id?: string; children?: any; }; let sourceCounter = 0; function createSource(map: MapInstance, id: string, props: SourceProps) { // @ts-ignore if (map.style && map.style._loaded) { const options = {...props}; delete options.id; delete options.children; // @ts-ignore map.addSource(id, options); return map.getSource(id); } return null; } /* eslint-disable complexity */ function updateSource(source: AnySourceImplementation, props: SourceProps, prevProps: SourceProps) { assert(props.id === prevProps.id, 'source id changed'); assert(props.type === prevProps.type, 'source type changed'); let changedKey = ''; let changedKeyCount = 0; for (const key in props) { if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) { changedKey = key; changedKeyCount++; } } if (!changedKeyCount) { return; } const type = props.type; if (type === 'geojson') { (source as GeoJSONSourceImplementation).setData(props.data); } else if (type === 'image') { (source as ImageSourceImplementation).updateImage({ url: props.url, coordinates: props.coordinates }); } else if ('setCoordinates' in source && changedKeyCount === 1 && changedKey === 'coordinates') { source.setCoordinates((props as unknown as ImageSourceSpecification).coordinates); } else if ('setUrl' in source && changedKey === 'url') { source.setUrl((props as VectorSourceSpecification).url); } else if ('setTiles' in source && changedKey === 'tiles') { source.setTiles((props as VectorSourceSpecification).tiles); } else { // eslint-disable-next-line console.warn(`Unable to update prop: ${changedKey}`); } } /* eslint-enable complexity */ export function Source(props: SourceProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-source-${sourceCounter++}`, []); useEffect(() => { if (map) { /* global setTimeout */ const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getSource(id)) { // Parent effects are destroyed before child ones, see // https://github.com/facebook/react/issues/16728 // Source can only be removed after all child layers are removed const allLayers = map.getStyle()?.layers; if (allLayers) { for (const layer of allLayers) { // @ts-ignore (2339) source does not exist on all layer types if (layer.source === id) { map.removeLayer(layer.id); } } } map.removeSource(id); } }; } return undefined; }, [map]); // @ts-ignore let source = map && map.style && map.getSource(id); if (source) { updateSource(source, props, propsRef.current); } else { source = createSource(map, id, props); } propsRef.current = props; return ( (source && React.Children.map( props.children, child => child && cloneElement(child, { source: id }) )) || null ); } ================================================ FILE: modules/react-mapbox/src/components/use-control.ts ================================================ import {useContext, useMemo, useEffect} from 'react'; import type {IControl, ControlPosition} from '../types/lib'; import {MapContext} from './map'; import type {MapContextValue} from './map'; type ControlOptions = { position?: ControlPosition; }; export function useControl( onCreate: (context: MapContextValue) => T, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onAdd: (context: MapContextValue) => void, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, arg1?: ((context: MapContextValue) => void) | ControlOptions, arg2?: ((context: MapContextValue) => void) | ControlOptions, arg3?: ControlOptions ): T { const context = useContext(MapContext); const ctrl = useMemo(() => onCreate(context), []); useEffect(() => { const opts = (arg3 || arg2 || arg1) as ControlOptions; const onAdd = typeof arg1 === 'function' && typeof arg2 === 'function' ? arg1 : null; const onRemove = typeof arg2 === 'function' ? arg2 : typeof arg1 === 'function' ? arg1 : null; const {map} = context; if (!map.hasControl(ctrl)) { map.addControl(ctrl, opts?.position); if (onAdd) { onAdd(context); } } return () => { if (onRemove) { onRemove(context); } // Map might have been removed (parent effects are destroyed before child ones) if (map.hasControl(ctrl)) { map.removeControl(ctrl); } }; }, []); return ctrl; } ================================================ FILE: modules/react-mapbox/src/components/use-map.tsx ================================================ import * as React from 'react'; import {useState, useCallback, useMemo, useContext} from 'react'; import {MapRef} from '../mapbox/create-ref'; import {MapContext} from './map'; type MountedMapsContextValue = { maps: {[id: string]: MapRef}; onMapMount: (map: MapRef, id: string) => void; onMapUnmount: (id: string) => void; }; export const MountedMapsContext = React.createContext(null); export const MapProvider: React.FC<{children?: React.ReactNode}> = props => { const [maps, setMaps] = useState<{[id: string]: MapRef}>({}); const onMapMount = useCallback((map: MapRef, id: string = 'default') => { setMaps(currMaps => { if (id === 'current') { throw new Error("'current' cannot be used as map id"); } if (currMaps[id]) { throw new Error(`Multiple maps with the same id: ${id}`); } return {...currMaps, [id]: map}; }); }, []); const onMapUnmount = useCallback((id: string = 'default') => { setMaps(currMaps => { if (currMaps[id]) { const nextMaps = {...currMaps}; delete nextMaps[id]; return nextMaps; } return currMaps; }); }, []); return ( {props.children} ); }; export type MapCollection = { [id: string]: MapRef | undefined; current?: MapRef; }; export function useMap(): MapCollection { const maps = useContext(MountedMapsContext)?.maps; const currentMap = useContext(MapContext); const mapsWithCurrent = useMemo(() => { return {...maps, current: currentMap?.map}; }, [maps, currentMap]); return mapsWithCurrent as MapCollection; } ================================================ FILE: modules/react-mapbox/src/index.ts ================================================ import {Map} from './components/map'; export {Map}; export default Map; export {Marker} from './components/marker'; export {Popup} from './components/popup'; export {AttributionControl} from './components/attribution-control'; export {FullscreenControl} from './components/fullscreen-control'; export {GeolocateControl} from './components/geolocate-control'; export {NavigationControl} from './components/navigation-control'; export {ScaleControl} from './components/scale-control'; export {Source} from './components/source'; export {Layer} from './components/layer'; export {useControl} from './components/use-control'; export {MapProvider, useMap} from './components/use-map'; export type {MapProps} from './components/map'; export type {MapRef} from './mapbox/create-ref'; export type {MarkerProps} from './components/marker'; export type {PopupProps} from './components/popup'; export type {AttributionControlProps} from './components/attribution-control'; export type {FullscreenControlProps} from './components/fullscreen-control'; export type {GeolocateControlProps} from './components/geolocate-control'; export type {NavigationControlProps} from './components/navigation-control'; export type {ScaleControlProps} from './components/scale-control'; export type {SourceProps} from './components/source'; export type {LayerProps} from './components/layer'; // Types export * from './types/common'; export * from './types/events'; export * from './types/lib'; export * from './types/style-spec'; ================================================ FILE: modules/react-mapbox/src/mapbox/create-ref.ts ================================================ import type {MapInstance} from '../types/lib'; import {LngLatLike, PointLike} from '../types/common'; import type Mapbox from './mapbox'; /** These methods may break the react binding if called directly */ const skipMethods = [ 'setMaxBounds', 'setMinZoom', 'setMaxZoom', 'setMinPitch', 'setMaxPitch', 'setRenderWorldCopies', 'setProjection', 'setStyle', 'addSource', 'removeSource', 'addLayer', 'removeLayer', 'setLayerZoomRange', 'setFilter', 'setPaintProperty', 'setLayoutProperty', 'setLight', 'setTerrain', 'setFog', 'remove' ] as const; export type MapRef = { getMap(): MapInstance; } & Omit; export default function createRef(mapInstance: Mapbox): MapRef | null { if (!mapInstance) { return null; } const map = mapInstance.map; const ref: any = { getMap: () => map, // Overwrite getters to use our shadow transform getCenter: () => mapInstance.transform.center, getZoom: () => mapInstance.transform.zoom, getBearing: () => mapInstance.transform.bearing, getPitch: () => mapInstance.transform.pitch, getPadding: () => mapInstance.transform.padding, getBounds: () => mapInstance.transform.getBounds(), project: (lnglat: LngLatLike) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.project(lnglat); map.transform = tr; return result; }, unproject: (point: PointLike) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.unproject(point); map.transform = tr; return result; }, // options diverge between mapbox and maplibre queryTerrainElevation: (lnglat: LngLatLike, options?: any) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.queryTerrainElevation(lnglat, options); map.transform = tr; return result; }, queryRenderedFeatures: (geometry?: any, options?: any) => { const tr = map.transform; map.transform = mapInstance.transform; const result = map.queryRenderedFeatures(geometry, options); map.transform = tr; return result; } }; for (const key of getMethodNames(map)) { // @ts-expect-error if (!(key in ref) && !skipMethods.includes(key)) { ref[key] = map[key].bind(map); } } return ref; } function getMethodNames(obj: Object) { const result = new Set(); let proto = obj; while (proto) { for (const key of Object.getOwnPropertyNames(proto)) { if ( key[0] !== '_' && typeof obj[key] === 'function' && key !== 'fire' && key !== 'setEventedParent' ) { result.add(key); } } proto = Object.getPrototypeOf(proto); } return Array.from(result); } ================================================ FILE: modules/react-mapbox/src/mapbox/mapbox.ts ================================================ import {transformToViewState, compareViewStateWithTransform} from '../utils/transform'; import {ProxyTransform, createProxyTransform} from './proxy-transform'; import {normalizeStyle} from '../utils/style-utils'; import {deepEqual} from '../utils/deep-equal'; import type { ViewState, Point, PointLike, PaddingOptions, ImmutableLike, LngLatBoundsLike, MapGeoJSONFeature } from '../types/common'; import type { StyleSpecification, LightSpecification, TerrainSpecification, FogSpecification, ProjectionSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; import type {Transform} from '../types/internal'; import type { MapCallbacks, ViewStateChangeEvent, MapEvent, ErrorEvent, MapMouseEvent } from '../types/events'; export type MapboxProps = Partial & MapCallbacks & { // Init options mapboxAccessToken?: string; /** Camera options used when constructing the Map instance */ initialViewState?: Partial & { /** The initial bounds of the map. If bounds is specified, it overrides longitude, latitude and zoom options. */ bounds?: LngLatBoundsLike; /** A fitBounds options object to use only when setting the bounds option. */ fitBoundsOptions?: { offset?: PointLike; minZoom?: number; maxZoom?: number; padding?: number | PaddingOptions; }; }; /** If provided, render into an external WebGL context */ gl?: WebGLRenderingContext; /** For external controller to override the camera state */ viewState?: ViewState & { width: number; height: number; }; // Styling /** Mapbox style */ mapStyle?: string | StyleSpecification | ImmutableLike; /** Enable diffing when the map style changes * @default true */ styleDiffing?: boolean; /** The projection property of the style. Must conform to the Projection Style Specification. * @default 'mercator' */ projection?: ProjectionSpecification | ProjectionSpecification['name']; /** The fog property of the style. Must conform to the Fog Style Specification . * If `undefined` is provided, removes the fog from the map. */ fog?: FogSpecification; /** Light properties of the map. */ light?: LightSpecification; /** Terrain property of the style. Must conform to the Terrain Style Specification . * If `undefined` is provided, removes terrain from the map. */ terrain?: TerrainSpecification; /** Default layers to query on pointer events */ interactiveLayerIds?: string[]; /** CSS cursor */ cursor?: string; }; const DEFAULT_STYLE = {version: 8, sources: {}, layers: []} as StyleSpecification; const DEFAULT_SETTINGS = { minZoom: 0, maxZoom: 22, minPitch: 0, maxPitch: 85, maxBounds: [-180, -85.051129, 180, 85.051129], projection: 'mercator', renderWorldCopies: true }; const pointerEvents = { mousedown: 'onMouseDown', mouseup: 'onMouseUp', mouseover: 'onMouseOver', mousemove: 'onMouseMove', click: 'onClick', dblclick: 'onDblClick', mouseenter: 'onMouseEnter', mouseleave: 'onMouseLeave', mouseout: 'onMouseOut', contextmenu: 'onContextMenu', touchstart: 'onTouchStart', touchend: 'onTouchEnd', touchmove: 'onTouchMove', touchcancel: 'onTouchCancel' }; const cameraEvents = { movestart: 'onMoveStart', move: 'onMove', moveend: 'onMoveEnd', dragstart: 'onDragStart', drag: 'onDrag', dragend: 'onDragEnd', zoomstart: 'onZoomStart', zoom: 'onZoom', zoomend: 'onZoomEnd', rotatestart: 'onRotateStart', rotate: 'onRotate', rotateend: 'onRotateEnd', pitchstart: 'onPitchStart', pitch: 'onPitch', pitchend: 'onPitchEnd' }; const otherEvents = { wheel: 'onWheel', boxzoomstart: 'onBoxZoomStart', boxzoomend: 'onBoxZoomEnd', boxzoomcancel: 'onBoxZoomCancel', resize: 'onResize', load: 'onLoad', render: 'onRender', idle: 'onIdle', remove: 'onRemove', data: 'onData', styledata: 'onStyleData', sourcedata: 'onSourceData', error: 'onError' }; const settingNames = [ 'minZoom', 'maxZoom', 'minPitch', 'maxPitch', 'maxBounds', 'projection', 'renderWorldCopies' ]; const handlerNames = [ 'scrollZoom', 'boxZoom', 'dragRotate', 'dragPan', 'keyboard', 'doubleClickZoom', 'touchZoomRotate', 'touchPitch' ]; /** * A wrapper for mapbox-gl's Map class */ export default class Mapbox { private _MapClass: {new (options: any): MapInstance}; /** mapboxgl.Map instance */ private _map: MapInstance = null; /** User-supplied props */ props: MapboxProps; /** The transform that replaces native map.transform to resolve changes vs. React props * See proxy-transform.ts */ private _proxyTransform: ProxyTransform; // Internal states /** Making updates driven by React props. Do not trigger React callbacks to avoid infinite loop */ private _internalUpdate: boolean = false; /** Map is currently rendering */ private _inRender: boolean = false; /** Map features under the pointer */ private _hoveredFeatures: MapGeoJSONFeature[] = null; /** View state changes driven by React props * They still need to fire move/etc. events because controls such as marker/popup * subscribe to the move event internally to update their position * React callbacks like onMove are not called for these */ private _deferredEvents: { move: boolean; zoom: boolean; pitch: boolean; rotate: boolean; } = { move: false, zoom: false, pitch: false, rotate: false }; static savedMaps: Mapbox[] = []; constructor( MapClass: {new (options: any): MapInstance}, props: MapboxProps, container: HTMLDivElement ) { this._MapClass = MapClass; this.props = props; this._initialize(container); } get map(): MapInstance { return this._map; } get transform(): Transform { return this._map.transform; } setProps(props: MapboxProps) { const oldProps = this.props; this.props = props; const settingsChanged = this._updateSettings(props, oldProps); const sizeChanged = this._updateSize(props); const viewStateChanged = this._updateViewState(props, true); this._updateStyle(props, oldProps); this._updateStyleComponents(props, oldProps); this._updateHandlers(props, oldProps); // If 1) view state has changed to match props and // 2) the props change is not triggered by map events, // it's driven by an external state change. Redraw immediately if (settingsChanged || sizeChanged || (viewStateChanged && !this._map.isMoving())) { this.redraw(); } } static reuse(props: MapboxProps, container: HTMLDivElement): Mapbox { const that = Mapbox.savedMaps.pop(); if (!that) { return null; } const map = that.map; // When reusing the saved map, we need to reparent the map(canvas) and other child nodes // intoto the new container from the props. // Step 1: reparenting child nodes from old container to new container const oldContainer = map.getContainer(); container.className = oldContainer.className; while (oldContainer.childNodes.length > 0) { container.appendChild(oldContainer.childNodes[0]); } // Step 2: replace the internal container with new container from the react component // @ts-ignore map._container = container; // Step 4: apply new props that.setProps({...props, styleDiffing: false}); map.resize(); const {initialViewState} = props; if (initialViewState) { if (initialViewState.bounds) { map.fitBounds(initialViewState.bounds, {...initialViewState.fitBoundsOptions, duration: 0}); } else { that._updateViewState(initialViewState, false); } } // Simulate load event if (map.isStyleLoaded()) { map.fire('load'); } else { map.once('styledata', () => map.fire('load')); } // Force reload // @ts-ignore map._update(); return that; } /* eslint-disable complexity,max-statements */ _initialize(container: HTMLDivElement) { const {props} = this; const {mapStyle = DEFAULT_STYLE} = props; const mapOptions = { ...props, ...props.initialViewState, accessToken: props.mapboxAccessToken || getAccessTokenFromEnv() || null, container, style: normalizeStyle(mapStyle) }; const viewState = mapOptions.initialViewState || mapOptions.viewState || mapOptions; Object.assign(mapOptions, { center: [viewState.longitude || 0, viewState.latitude || 0], zoom: viewState.zoom || 0, pitch: viewState.pitch || 0, bearing: viewState.bearing || 0 }); if (props.gl) { // eslint-disable-next-line const getContext = HTMLCanvasElement.prototype.getContext; // Hijack canvas.getContext to return our own WebGLContext // This will be called inside the mapboxgl.Map constructor // @ts-expect-error HTMLCanvasElement.prototype.getContext = () => { // Unhijack immediately HTMLCanvasElement.prototype.getContext = getContext; return props.gl; }; } const map = new this._MapClass(mapOptions); // Props that are not part of constructor options if (viewState.padding) { map.setPadding(viewState.padding); } if (props.cursor) { map.getCanvas().style.cursor = props.cursor; } this._createProxyTransform(map); // Hack // Insert code into map's render cycle // eslint-disable-next-line @typescript-eslint/unbound-method const renderMap = map._render; map._render = (arg: number) => { // Hijacked to set this state flag this._inRender = true; renderMap.call(map, arg); this._inRender = false; }; // eslint-disable-next-line @typescript-eslint/unbound-method const runRenderTaskQueue = map._renderTaskQueue.run; map._renderTaskQueue.run = (arg: number) => { // This is where camera updates from input handler/animation happens // And where all view state change events are fired this._proxyTransform.$internalUpdate = true; runRenderTaskQueue.call(map._renderTaskQueue, arg); this._proxyTransform.$internalUpdate = false; this._fireDefferedEvents(); }; // eslint-disable-next-line @typescript-eslint/unbound-method const jumpTo = map.jumpTo; map.jumpTo = (...args: Parameters) => { // This method will fire view state change events immediately this._proxyTransform.$internalUpdate = true; jumpTo.apply(map, args); this._proxyTransform.$internalUpdate = false; return map; }; // Insert code into map's event pipeline // eslint-disable-next-line @typescript-eslint/unbound-method const fireEvent = map.fire; map.fire = this._fireEvent.bind(this, fireEvent); // add listeners map.on('styledata', () => { this._updateStyleComponents(this.props, {}); }); map.on('sourcedata', () => { this._updateStyleComponents(this.props, {}); }); for (const eventName in pointerEvents) { map.on(eventName, this._onPointerEvent); } for (const eventName in cameraEvents) { map.on(eventName, this._onCameraEvent); } for (const eventName in otherEvents) { map.on(eventName, this._onEvent); } this._map = map; } /* eslint-enable complexity,max-statements */ recycle() { // Clean up unnecessary elements before storing for reuse. const container = this.map.getContainer(); const children = container.querySelector('[mapboxgl-children]'); children?.remove(); Mapbox.savedMaps.push(this); } destroy() { this._map.remove(); } // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next // render cycle, which is managed by Mapbox's animation loop. // This removes the synchronization issue caused by requestAnimationFrame. redraw() { const map = this._map as any; // map._render will throw error if style does not exist // https://github.com/mapbox/mapbox-gl-js/blob/fb9fc316da14e99ff4368f3e4faa3888fb43c513 // /src/ui/map.js#L1834 if (!this._inRender && map.style) { // cancel the scheduled update if (map._frame) { map._frame.cancel(); map._frame = null; } // the order is important - render() may schedule another update map._render(); } } _createProxyTransform(map: any) { const proxyTransform = createProxyTransform(map.transform); map.transform = proxyTransform; map.painter.transform = proxyTransform; this._proxyTransform = proxyTransform; } /* Trigger map resize if size is controlled @param {object} nextProps @returns {bool} true if size has changed */ _updateSize(nextProps: MapboxProps): boolean { // Check if size is controlled const {viewState} = nextProps; if (viewState) { const map = this._map; if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) { map.resize(); return true; } } return false; } // Adapted from map.jumpTo /* Update camera to match props @param {object} nextProps @param {bool} triggerEvents - should fire camera events @returns {bool} true if anything is changed */ _updateViewState(nextProps: MapboxProps, triggerEvents: boolean): boolean { const viewState: Partial = nextProps.viewState || nextProps; const tr = this._proxyTransform; const {zoom, pitch, bearing} = tr; const changed = compareViewStateWithTransform(this._proxyTransform, viewState); tr.$reactViewState = viewState; if (changed && triggerEvents) { const deferredEvents = this._deferredEvents; // Delay DOM control updates to the next render cycle deferredEvents.move = true; deferredEvents.zoom ||= zoom !== tr.zoom; deferredEvents.rotate ||= bearing !== tr.bearing; deferredEvents.pitch ||= pitch !== tr.pitch; } return changed; } /* Update camera constraints and projection settings to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateSettings(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; for (const propName of settingNames) { const propPresent = propName in nextProps || propName in currProps; if (propPresent && !deepEqual(nextProps[propName], currProps[propName])) { changed = true; const nextValue = propName in nextProps ? nextProps[propName] : DEFAULT_SETTINGS[propName]; const setter = map[`set${propName[0].toUpperCase()}${propName.slice(1)}`]; setter?.call(map, nextValue); } } return changed; } /* Update map style to match props @param {object} nextProps @param {object} currProps @returns {bool} true if style is changed */ _updateStyle(nextProps: MapboxProps, currProps: MapboxProps): boolean { if (nextProps.cursor !== currProps.cursor) { this._map.getCanvas().style.cursor = nextProps.cursor || ''; } if (nextProps.mapStyle !== currProps.mapStyle) { const {mapStyle = DEFAULT_STYLE, styleDiffing = true} = nextProps; const options: any = { diff: styleDiffing }; if ('localIdeographFontFamily' in nextProps) { // @ts-ignore Mapbox specific prop options.localIdeographFontFamily = nextProps.localIdeographFontFamily; } this._map.setStyle(normalizeStyle(mapStyle), options); return true; } return false; } /* Update fog, light and terrain to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateStyleComponents(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; if (map.isStyleLoaded()) { if ('light' in nextProps && map.setLight && !deepEqual(nextProps.light, currProps.light)) { changed = true; map.setLight(nextProps.light); } if ('fog' in nextProps && map.setFog && !deepEqual(nextProps.fog, currProps.fog)) { changed = true; map.setFog(nextProps.fog); } if ( 'terrain' in nextProps && map.setTerrain && !deepEqual(nextProps.terrain, currProps.terrain) ) { if (!nextProps.terrain || map.getSource(nextProps.terrain.source)) { changed = true; map.setTerrain(nextProps.terrain); } } } return changed; } /* Update interaction handlers to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ _updateHandlers(nextProps: MapboxProps, currProps: MapboxProps): boolean { const map = this._map; let changed = false; for (const propName of handlerNames) { const newValue = nextProps[propName] ?? true; const oldValue = currProps[propName] ?? true; if (!deepEqual(newValue, oldValue)) { changed = true; if (newValue) { map[propName].enable(newValue); } else { map[propName].disable(); } } } return changed; } _onEvent = (e: MapEvent) => { // @ts-ignore const cb = this.props[otherEvents[e.type]]; if (cb) { cb(e); } else if (e.type === 'error') { console.error((e as ErrorEvent).error); // eslint-disable-line } }; private _queryRenderedFeatures(point: Point) { const map = this._map; const {interactiveLayerIds = []} = this.props; try { return map.queryRenderedFeatures(point, { layers: interactiveLayerIds.filter(map.getLayer.bind(map)) }); } catch { // May fail if style is not loaded return []; } } _updateHover(e: MapMouseEvent) { const {props} = this; const shouldTrackHoveredFeatures = props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave); if (shouldTrackHoveredFeatures) { const eventType = e.type; const wasHovering = this._hoveredFeatures?.length > 0; const features = this._queryRenderedFeatures(e.point); const isHovering = features.length > 0; if (!isHovering && wasHovering) { e.type = 'mouseleave'; this._onPointerEvent(e); } this._hoveredFeatures = features; if (isHovering && !wasHovering) { e.type = 'mouseenter'; this._onPointerEvent(e); } e.type = eventType; } else { this._hoveredFeatures = null; } } _onPointerEvent = (e: MapMouseEvent) => { if (e.type === 'mousemove' || e.type === 'mouseout') { this._updateHover(e); } // @ts-ignore const cb = this.props[pointerEvents[e.type]]; if (cb) { if (this.props.interactiveLayerIds && e.type !== 'mouseover' && e.type !== 'mouseout') { e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point); } cb(e); delete e.features; } }; _onCameraEvent = (e: ViewStateChangeEvent) => { if (!this._internalUpdate) { // @ts-ignore const cb = this.props[cameraEvents[e.type]]; const tr = this._proxyTransform; if (cb) { e.viewState = transformToViewState(tr.$proposedTransform ?? tr); cb(e); } if (e.type === 'moveend') { tr.$proposedTransform = null; } } if (e.type in this._deferredEvents) { this._deferredEvents[e.type] = false; } }; _fireEvent(baseFire: Function, event: string | MapEvent, properties?: object) { const map = this._map; const tr = this._proxyTransform; // Always expose the controlled transform to controls/end user const internal = tr.$internalUpdate; try { tr.$internalUpdate = false; baseFire.call(map, event, properties); } finally { tr.$internalUpdate = internal; } return map; } // If there are camera changes driven by props, invoke camera events so that DOM controls are synced _fireDefferedEvents() { const map = this._map; this._internalUpdate = true; for (const eventType in this._deferredEvents) { if (this._deferredEvents[eventType]) { map.fire(eventType); } } this._internalUpdate = false; } } /** * Access token can be provided via one of: * mapboxAccessToken prop * access_token query parameter * MapboxAccessToken environment variable * REACT_APP_MAPBOX_ACCESS_TOKEN environment variable * @returns access token */ function getAccessTokenFromEnv(): string { let accessToken = null; /* global location, process */ if (typeof location !== 'undefined') { const match = /access_token=([^&\/]*)/.exec(location.search); accessToken = match && match[1]; } // Note: This depends on bundler plugins (e.g. webpack) importing environment correctly try { // eslint-disable-next-line no-process-env accessToken = accessToken || process.env.MapboxAccessToken; } catch { // ignore } try { // eslint-disable-next-line no-process-env accessToken = accessToken || process.env.REACT_APP_MAPBOX_ACCESS_TOKEN; } catch { // ignore } return accessToken; } ================================================ FILE: modules/react-mapbox/src/mapbox/proxy-transform.ts ================================================ import type {Transform} from '../types/internal'; import type {ViewState, LngLat} from '../types/common'; import {applyViewStateToTransform, isViewStateControlled} from '../utils/transform'; /** * Mapbox map is stateful. * During method calls/user interactions, map.transform is mutated and deviate from user-supplied props. * In order to control the map reactively, we trap the transform mutations with a proxy, * which reflects the view state resolved from both user-supplied props and the underlying state */ export type ProxyTransform = Transform & { $internalUpdate: boolean; $proposedTransform: Transform | null; $reactViewState: Partial; }; // These are Transform class methods that: // + do not mutate any view state properties // + populate private members derived from view state properties // They should always reflect the state of their owning instance and NOT trigger any proxied getter/setter const unproxiedMethods = new Set([ '_calcMatrices', '_calcFogMatrices', '_updateCameraState', '_updateSeaLevelZoom' ]); export function createProxyTransform(tr: Transform): ProxyTransform { let internalUpdate = false; let reactViewState: Partial = {}; /** * Reflects view state set by react props * This is the transform seen by painter, style etc. */ const controlledTransform: Transform = tr; /** Populated during camera move (handler/easeTo) if there is a discrepency between react props and proposed view state * This is the transform seen by Mapbox's input handlers */ let proposedTransform: Transform | null = null; const handlers: ProxyHandler = { get(target: Transform, prop: string) { // Props added by us if (prop === '$reactViewState') { return reactViewState; } if (prop === '$proposedTransform') { return proposedTransform; } if (prop === '$internalUpdate') { return internalUpdate; } // Ugly - this method is called from HandlerManager bypassing zoom setter if (prop === '_setZoom') { return (z: number) => { if (internalUpdate) { proposedTransform?.[prop](z); } if (!Number.isFinite(reactViewState.zoom)) { controlledTransform[prop](z); } }; } // Ugly - this method is called from HandlerManager and mutates transform._camera if ( internalUpdate && prop === '_translateCameraConstrained' && isViewStateControlled(reactViewState) ) { proposedTransform = proposedTransform || controlledTransform.clone(); } if (unproxiedMethods.has(prop)) { // When this function is executed, it updates both transforms respectively return function (...parms: unknown[]) { proposedTransform?.[prop](...parms); controlledTransform[prop](...parms); }; } // Expose the proposed transform to input handlers if (internalUpdate && proposedTransform) { return proposedTransform[prop]; } // Expose the controlled transform to renderer, markers, and event listeners return controlledTransform[prop]; }, set(target: Transform, prop: string, value: unknown) { // Props added by us if (prop === '$reactViewState') { reactViewState = value as Partial; applyViewStateToTransform(controlledTransform, reactViewState); return true; } if (prop === '$proposedTransform') { proposedTransform = value as Transform; return true; } if (prop === '$internalUpdate') { internalUpdate = value as boolean; return true; } // Controlled props let controlledValue = value; if (prop === 'center' || prop === '_center') { if (Number.isFinite(reactViewState.longitude) || Number.isFinite(reactViewState.latitude)) { // @ts-expect-error LngLat constructor is not typed controlledValue = new value.constructor( reactViewState.longitude ?? (value as LngLat).lng, reactViewState.latitude ?? (value as LngLat).lat ); } } else if (prop === 'zoom' || prop === '_zoom' || prop === '_seaLevelZoom') { if (Number.isFinite(reactViewState.zoom)) { controlledValue = controlledTransform[prop]; } } else if (prop === '_centerAltitude') { if (Number.isFinite(reactViewState.elevation)) { controlledValue = controlledTransform[prop]; } } else if (prop === 'pitch' || prop === '_pitch') { if (Number.isFinite(reactViewState.pitch)) { controlledValue = controlledTransform[prop]; } } else if (prop === 'bearing' || prop === 'rotation' || prop === 'angle') { if (Number.isFinite(reactViewState.bearing)) { controlledValue = controlledTransform[prop]; } } // During camera update, we save view states that are overriden by controlled values in proposedTransform if (internalUpdate && controlledValue !== value) { proposedTransform = proposedTransform || controlledTransform.clone(); } if (internalUpdate && proposedTransform) { proposedTransform[prop] = value; } // controlledTransform is not exposed to view state mutation controlledTransform[prop] = controlledValue; return true; } }; return new Proxy(tr, handlers) as ProxyTransform; } ================================================ FILE: modules/react-mapbox/src/types/common.ts ================================================ import type {PaddingOptions} from 'mapbox-gl'; export type { Point, PointLike, LngLat, LngLatLike, LngLatBounds, LngLatBoundsLike, PaddingOptions, GeoJSONFeature as MapGeoJSONFeature } from 'mapbox-gl'; /* Public */ /** Describes the camera's state */ export type ViewState = { /** Longitude at map center */ longitude: number; /** Latitude at map center */ latitude: number; /** Map zoom level */ zoom: number; /** Map rotation bearing in degrees counter-clockwise from north */ bearing: number; /** Map angle in degrees at which the camera is looking at the ground */ pitch: number; /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ padding: PaddingOptions; /** Center elevation on terrain */ elevation?: number; }; export interface ImmutableLike { toJS: () => T; } ================================================ FILE: modules/react-mapbox/src/types/events.ts ================================================ import type {ViewState, LngLat} from './common'; import { Marker, Popup, GeolocateControl, MapEvent, MapEventOf, ErrorEvent, MapMouseEvent, MapTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent } from 'mapbox-gl'; export type { MapEvent, ErrorEvent, MapMouseEvent, MapTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent }; export type MapBoxZoomEvent = | MapEventOf<'boxzoomstart'> | MapEventOf<'boxzoomend'> | MapEventOf<'boxzoomcancel'>; export type MapCallbacks = { onMouseDown?: (e: MapMouseEvent) => void; onMouseUp?: (e: MapMouseEvent) => void; onMouseOver?: (e: MapMouseEvent) => void; onMouseMove?: (e: MapMouseEvent) => void; onClick?: (e: MapMouseEvent) => void; onDblClick?: (e: MapMouseEvent) => void; onMouseEnter?: (e: MapMouseEvent) => void; onMouseLeave?: (e: MapMouseEvent) => void; onMouseOut?: (e: MapMouseEvent) => void; onContextMenu?: (e: MapMouseEvent) => void; onTouchStart?: (e: MapTouchEvent) => void; onTouchEnd?: (e: MapTouchEvent) => void; onTouchMove?: (e: MapTouchEvent) => void; onTouchCancel?: (e: MapTouchEvent) => void; onMoveStart?: (e: ViewStateChangeEvent) => void; onMove?: (e: ViewStateChangeEvent) => void; onMoveEnd?: (e: ViewStateChangeEvent) => void; onDragStart?: (e: ViewStateChangeEvent) => void; onDrag?: (e: ViewStateChangeEvent) => void; onDragEnd?: (e: ViewStateChangeEvent) => void; onZoomStart?: (e: ViewStateChangeEvent) => void; onZoom?: (e: ViewStateChangeEvent) => void; onZoomEnd?: (e: ViewStateChangeEvent) => void; onRotateStart?: (e: ViewStateChangeEvent) => void; onRotate?: (e: ViewStateChangeEvent) => void; onRotateEnd?: (e: ViewStateChangeEvent) => void; onPitchStart?: (e: ViewStateChangeEvent) => void; onPitch?: (e: ViewStateChangeEvent) => void; onPitchEnd?: (e: ViewStateChangeEvent) => void; onWheel?: (e: MapWheelEvent) => void; onBoxZoomStart?: (e: MapBoxZoomEvent) => void; onBoxZoomEnd?: (e: MapBoxZoomEvent) => void; onBoxZoomCancel?: (e: MapBoxZoomEvent) => void; onResize?: (e: MapEvent) => void; onLoad?: (e: MapEvent) => void; onRender?: (e: MapEvent) => void; onIdle?: (e: MapEvent) => void; onError?: (e: ErrorEvent) => void; onRemove?: (e: MapEvent) => void; onData?: (e: MapStyleDataEvent | MapSourceDataEvent) => void; onStyleData?: (e: MapStyleDataEvent) => void; onSourceData?: (e: MapSourceDataEvent) => void; }; interface IMapEvent { type: string; target: SourceT; originalEvent: OriginalEventT; } export interface Callbacks { [key: `on${string}`]: Function; } export type ViewStateChangeEvent = MapEventOf< | 'movestart' | 'move' | 'moveend' | 'zoomstart' | 'zoom' | 'zoomend' | 'rotatestart' | 'rotate' | 'rotateend' | 'dragstart' | 'drag' | 'dragend' | 'pitchstart' | 'pitch' | 'pitchend' > & { viewState: ViewState; }; export type PopupEvent = { type: 'open' | 'close'; target: Popup; }; export type MarkerEvent = IMapEvent; export type MarkerDragEvent = MarkerEvent & { type: 'dragstart' | 'drag' | 'dragend'; lngLat: LngLat; }; export type GeolocateEvent = IMapEvent; export type GeolocateResultEvent = GeolocateEvent & GeolocationPosition; export type GeolocateErrorEvent = GeolocateEvent & GeolocationPositionError; ================================================ FILE: modules/react-mapbox/src/types/internal.ts ================================================ // Internal types import type {Map} from 'mapbox-gl'; export type Transform = Map['transform']; export type { GeoJSONSource as GeoJSONSourceImplementation, ImageSource as ImageSourceImplementation, CanvasSource as CanvasSourceImplementation, VectorTileSource as VectorSourceImplementation, RasterTileSource as RasterSourceImplementation, RasterDemTileSource as RasterDemSourceImplementation, VideoSource as VideoSourceImplementation, Source as AnySourceImplementation } from 'mapbox-gl'; ================================================ FILE: modules/react-mapbox/src/types/lib.ts ================================================ import type { Map, MapOptions, Marker, MarkerOptions, Popup, PopupOptions, AttributionControl, AttributionControlOptions, FullscreenControl, FullscreenControlOptions, GeolocateControl, GeolocateControlOptions, NavigationControl, NavigationControlOptions, ScaleControl, ScaleControlOptions } from 'mapbox-gl'; export type { ControlPosition, IControl, Map as MapInstance, MapOptions, Marker as MarkerInstance, MarkerOptions, Popup as PopupInstance, PopupOptions, AttributionControl as AttributionControlInstance, AttributionControlOptions, FullscreenControl as FullscreenControlInstance, FullscreenControlOptions, GeolocateControl as GeolocateControlInstance, GeolocateControlOptions, NavigationControl as NavigationControlInstance, NavigationControlOptions, ScaleControl as ScaleControlInstance, ScaleControlOptions, CustomLayerInterface } from 'mapbox-gl'; /** * A user-facing type that represents the minimal intersection between Mapbox and Maplibre * User provided `mapLib` is supposed to implement this interface * Only losely typed for compatibility */ export interface MapLib { supported?: (options: any) => boolean; Map: {new (options: MapOptions): Map}; Marker: {new (options: MarkerOptions): Marker}; Popup: {new (options: PopupOptions): Popup}; AttributionControl: {new (options: AttributionControlOptions): AttributionControl}; FullscreenControl: {new (options: FullscreenControlOptions): FullscreenControl}; GeolocateControl: {new (options: GeolocateControlOptions): GeolocateControl}; NavigationControl: {new (options: NavigationControlOptions): NavigationControl}; ScaleControl: {new (options: ScaleControlOptions): ScaleControl}; } ================================================ FILE: modules/react-mapbox/src/types/style-spec.ts ================================================ /* * Mapbox Style Specification types */ export type CanvasSourceSpecification = { type: 'canvas'; coordinates: [[number, number], [number, number], [number, number], [number, number]]; animate?: boolean; canvas: string | HTMLCanvasElement; }; export type { // Layers LayerSpecification, FillLayerSpecification, LineLayerSpecification, SymbolLayerSpecification, CircleLayerSpecification, HeatmapLayerSpecification, FillExtrusionLayerSpecification, RasterLayerSpecification, RasterParticleLayerSpecification, HillshadeLayerSpecification, ModelLayerSpecification, BackgroundLayerSpecification, SkyLayerSpecification, SlotLayerSpecification, ClipLayerSpecification, // Sources SourceSpecification, VectorSourceSpecification, RasterSourceSpecification, RasterDEMSourceSpecification, RasterArraySourceSpecification, GeoJSONSourceSpecification, VideoSourceSpecification, ImageSourceSpecification, ModelSourceSpecification, // Style StyleSpecification, LightSpecification, FogSpecification, TerrainSpecification, ProjectionSpecification } from 'mapbox-gl'; ================================================ FILE: modules/react-mapbox/src/utils/apply-react-style.ts ================================================ import * as React from 'react'; // This is a simplified version of // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { if (!element || !styles) { return; } const style = element.style; for (const key in styles) { const value = styles[key]; if (Number.isFinite(value) && !unitlessNumber.test(key)) { style[key] = `${value}px`; } else { style[key] = value; } } } ================================================ FILE: modules/react-mapbox/src/utils/assert.ts ================================================ export default function assert(condition: any, message: string) { if (!condition) { throw new Error(message); } } ================================================ FILE: modules/react-mapbox/src/utils/compare-class-names.ts ================================================ /** Compare two classNames string and return the difference */ export function compareClassNames( prevClassName: string | undefined, nextClassName: string | undefined ): string[] | null { if (prevClassName === nextClassName) { return null; } const prevClassList = getClassList(prevClassName); const nextClassList = getClassList(nextClassName); const diff: string[] = []; for (const c of nextClassList) { if (!prevClassList.has(c)) { diff.push(c); } } for (const c of prevClassList) { if (!nextClassList.has(c)) { diff.push(c); } } return diff.length === 0 ? null : diff; } function getClassList(className: string | undefined) { return new Set(className ? className.trim().split(/\s+/) : []); } ================================================ FILE: modules/react-mapbox/src/utils/deep-equal.ts ================================================ import type {PointLike} from '../types/common'; /** * Compare two points * @param a * @param b * @returns true if the points are equal */ export function arePointsEqual(a?: PointLike, b?: PointLike): boolean { const ax = Array.isArray(a) ? a[0] : a ? a.x : 0; const ay = Array.isArray(a) ? a[1] : a ? a.y : 0; const bx = Array.isArray(b) ? b[0] : b ? b.x : 0; const by = Array.isArray(b) ? b[1] : b ? b.y : 0; return ax === bx && ay === by; } /* eslint-disable complexity */ /** * Compare any two objects * @param a * @param b * @returns true if the objects are deep equal */ export function deepEqual(a: any, b: any): boolean { if (a === b) { return true; } if (!a || !b) { return false; } if (Array.isArray(a)) { if (!Array.isArray(b) || a.length !== b.length) { return false; } for (let i = 0; i < a.length; i++) { if (!deepEqual(a[i], b[i])) { return false; } } return true; } else if (Array.isArray(b)) { return false; } if (typeof a === 'object' && typeof b === 'object') { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) { return false; } for (const key of aKeys) { if (!b.hasOwnProperty(key)) { return false; } if (!deepEqual(a[key], b[key])) { return false; } } return true; } return false; } ================================================ FILE: modules/react-mapbox/src/utils/set-globals.ts ================================================ export type GlobalSettings = { /** The map's default API URL for requesting tiles, styles, sprites, and glyphs. */ baseApiUrl?: string; /** The maximum number of images (raster tiles, sprites, icons) to load in parallel. * @default 16 */ maxParallelImageRequests?: number; /** The map's RTL text plugin. Necessary for supporting the Arabic and Hebrew languages, which are written right-to-left. */ RTLTextPlugin?: string | false; /** Provides an interface for external module bundlers such as Webpack or Rollup to package mapbox-gl's WebWorker into a separate class and integrate it with the library. Takes precedence over `workerUrl`. */ workerClass?: any; /** The number of web workers instantiated on a page with mapbox-gl maps. * @default 2 */ workerCount?: number; /** Provides an interface for loading mapbox-gl's WebWorker bundle from a self-hosted URL. * This is useful if your site needs to operate in a strict CSP (Content Security Policy) environment * wherein you are not allowed to load JavaScript code from a Blob URL, which is default behavior. */ workerUrl?: string; }; const globalSettings = [ 'baseApiUrl', 'maxParallelImageRequests', 'workerClass', 'workerCount', 'workerUrl' ] as const; export default function setGlobals(mapLib: any, props: GlobalSettings) { for (const key of globalSettings) { if (key in props) { mapLib[key] = props[key]; } } const { RTLTextPlugin = 'https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-rtl-text/v0.2.3/mapbox-gl-rtl-text.js' } = props; if ( RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === 'unavailable' ) { mapLib.setRTLTextPlugin( RTLTextPlugin, (error?: Error) => { if (error) { // eslint-disable-next-line console.error(error); } }, true ); } } ================================================ FILE: modules/react-mapbox/src/utils/style-utils.ts ================================================ import {ImmutableLike} from '../types/common'; import {StyleSpecification} from '../types/style-spec'; const refProps = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout']; // Prepare a map style object for diffing // If immutable - convert to plain object // Work around some issues in older styles that would fail Mapbox's diffing export function normalizeStyle( style: string | StyleSpecification | ImmutableLike ): string | StyleSpecification { if (!style) { return null; } if (typeof style === 'string') { return style; } if ('toJS' in style) { style = style.toJS(); } if (!style.layers) { return style; } const layerIndex = {}; for (const layer of style.layers) { layerIndex[layer.id] = layer; } const layers = style.layers.map(layer => { let normalizedLayer: typeof layer = null; if ('interactive' in layer) { normalizedLayer = Object.assign({}, layer); // Breaks style diffing :( // @ts-ignore legacy field not typed delete normalizedLayer.interactive; } // Style diffing doesn't work with refs so expand them out manually before diffing. // @ts-ignore legacy field not typed const layerRef = layerIndex[layer.ref]; if (layerRef) { normalizedLayer = normalizedLayer || Object.assign({}, layer); // @ts-ignore delete normalizedLayer.ref; // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/deref.js for (const propName of refProps) { if (propName in layerRef) { normalizedLayer[propName] = layerRef[propName]; } } } return normalizedLayer || layer; }); // Do not mutate the style object provided by the user return {...style, layers}; } ================================================ FILE: modules/react-mapbox/src/utils/transform.ts ================================================ import type {ViewState} from '../types/common'; import type {Transform} from '../types/internal'; /** * Capture a transform's current state * @param transform * @returns descriptor of the view state */ export function transformToViewState(tr: Transform): ViewState { return { longitude: tr.center.lng, latitude: tr.center.lat, zoom: tr._seaLevelZoom ?? tr.zoom, pitch: tr.pitch, bearing: tr.bearing, padding: tr.padding, elevation: tr._centerAltitude }; } /** Returns `true` if the given props can potentially override view state updates */ export function isViewStateControlled(v: Partial): boolean { return ( Number.isFinite(v.longitude) || Number.isFinite(v.latitude) || Number.isFinite(v.zoom) || Number.isFinite(v.pitch) || Number.isFinite(v.bearing) ); } /** * Returns `true` if transform needs to be updated to match view state */ export function compareViewStateWithTransform(tr: Transform, v: Partial): boolean { if (Number.isFinite(v.longitude) && tr.center.lng !== v.longitude) { return true; } if (Number.isFinite(v.latitude) && tr.center.lat !== v.latitude) { return true; } if (Number.isFinite(v.bearing) && tr.bearing !== v.bearing) { return true; } if (Number.isFinite(v.pitch) && tr.pitch !== v.pitch) { return true; } if (Number.isFinite(v.zoom) && (tr._seaLevelZoom ?? tr.zoom) !== v.zoom) { return true; } if (v.padding && !tr.isPaddingEqual(v.padding)) { return true; } return false; } function noOp() {} /* eslint-disable complexity */ /** * Mutate a transform to match the given view state. Should reverse `transformToViewState` * @param transform * @param viewState */ export function applyViewStateToTransform(tr: Transform, v: Partial) { // prevent constrain from running until all properties are set // eslint-disable-next-line @typescript-eslint/unbound-method const constrain = tr._constrain; // eslint-disable-next-line @typescript-eslint/unbound-method const calcMatrices = tr._calcMatrices; tr._constrain = noOp; tr._calcMatrices = noOp; if (Number.isFinite(v.bearing)) { tr.bearing = v.bearing; } if (Number.isFinite(v.pitch)) { tr.pitch = v.pitch; } if (v.padding && !tr.isPaddingEqual(v.padding)) { tr.padding = v.padding; } if (Number.isFinite(v.longitude) || Number.isFinite(v.latitude)) { const center = tr.center; // @ts-expect-error LngLat constructor is not typed tr._center = new center.constructor(v.longitude ?? center.lng, v.latitude ?? center.lat); } if (Number.isFinite(v.zoom)) { tr._centerAltitude = v.elevation ?? 0; if (tr.elevation) { tr._seaLevelZoom = v.zoom; const mercatorElevation = (tr.pixelsPerMeter / tr.worldSize) * tr._centerAltitude; const altitude = tr._mercatorZfromZoom(v.zoom); const minHeight = tr._mercatorZfromZoom(tr._maxZoom); const height = Math.max(altitude - mercatorElevation, minHeight); tr._setZoom(tr._zoomFromMercatorZ(height)); } else { tr._seaLevelZoom = null; tr.zoom = v.zoom; } } // restore methods tr._constrain = constrain; tr._calcMatrices = calcMatrices; if (!tr._unmodified) { tr._constrain(); tr._calcMatrices(); } } ================================================ FILE: modules/react-mapbox/src/utils/use-isomorphic-layout-effect.ts ================================================ // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts // useLayoutEffect but does not trigger warning in server-side rendering import {useEffect, useLayoutEffect} from 'react'; const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; export default useIsomorphicLayoutEffect; ================================================ FILE: modules/react-mapbox/test/components/controls.spec.jsx ================================================ import { Map, AttributionControl, FullscreenControl, GeolocateControl, NavigationControl, ScaleControl } from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Controls', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-attrib'), 'Rendered '); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-fullscreen'), 'Rendered '); const geolocateControlRef = {current: null}; root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-geolocate'), 'Rendered '); t.ok(geolocateControlRef.current, 'GeolocateControl created'); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-zoom-in'), 'Rendered '); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-ctrl-scale'), 'Rendered '); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/components/index.js ================================================ import './map.spec'; import './controls.spec'; import './source.spec'; import './layer.spec'; import './marker.spec'; import './popup.spec'; import './use-map.spec'; ================================================ FILE: modules/react-mapbox/test/components/layer.spec.jsx ================================================ import {Map, Source, Layer} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const pointLayer = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; const pointLayer2 = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#000000' }, layout: { visibility: 'none' } }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(mapRef.current.getLayer('my-layer'), 'Layer is added'); root.render( ); await sleep(1); t.is(mapRef.current.getLayer('my-layer').layout.visibility, 'none', 'Layer is updated'); root.render( ); await sleep(50); t.ok(mapRef.current.getLayer('my-layer'), 'Layer is added after style change'); root.render(); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); t.notOk(mapRef.current.getLayer('my-layer'), 'Layer is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/components/map.spec.jsx ================================================ /* global setTimeout */ import {Map} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Map', async t => { t.ok(Map, 'Map is defined'); const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let onloadCalled = 0; const onLoad = () => onloadCalled++; root.render( ); await waitForMapLoad(mapRef); t.ok(mapRef.current, 'Map is created'); t.is(mapRef.current.getCenter().lng, -100, 'longitude is set'); t.is(mapRef.current.getCenter().lat, 40, 'latitude is set'); t.is(mapRef.current.getZoom(), 4, 'zoom is set'); root.render( ); await sleep(1); t.is(mapRef.current.getCenter().lng, -122, 'longitude is updated'); t.is(mapRef.current.getCenter().lat, 38, 'latitude is updated'); t.is(mapRef.current.getZoom(), 14, 'zoom is updated'); t.is(onloadCalled, 1, 'onLoad is called'); root.unmount(); t.end(); }); test('Map#invalid token', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let errorMessage = null; const onError = ({error}) => { errorMessage = error.message; }; root.render( ); await waitForMapLoad(mapRef); t.ok(errorMessage?.includes('access token'), 'Throws on missing access token'); t.end(); }); test('Map#uncontrolled', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } let lastCenter; function onRender() { if (!mapRef.current) return; const center = mapRef.current.getCenter(); if (lastCenter) { t.ok(lastCenter.lng >= center.lng && lastCenter.lat >= center.lat, `animated to ${center}`); } lastCenter = center; } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#controlled#no-update', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender() { if (!mapRef.current) return; const center = mapRef.current.getCenter(); t.ok(center.lng === -100 && center.lat === 40, `map center should match props: ${center}`); } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#uncontrolled#delayedSettingsUpdate', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function App() { const [settings, setSettings] = React.useState({ maxPitch: 85 }); async function onLoad() { await sleep(1); setSettings({maxPitch: 60}); } return ( ); } root.render(); await waitForMapLoad(mapRef); await sleep(1); t.is(mapRef.current.getMaxPitch(), 60, 'maxPitch is updated'); }); test('Map#controlled#mirror-back', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs) { if (!mapRef.current) return; const center = mapRef.current.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setViewState(e.viewState)} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); test('Map#controlled#delayed-update', t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; function onLoad() { mapRef.current.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs) { if (!mapRef.current) return; const center = mapRef.current.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setTimeout(() => setViewState(e.viewState))} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); ================================================ FILE: modules/react-mapbox/test/components/marker.spec.jsx ================================================ import {Map, Marker} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Marker', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const markerRef = {current: null}; const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-marker'), 'Marker is attached to DOM'); t.ok(markerRef.current, 'Marker is created'); const marker = markerRef.current; const offset = marker.getOffset(); const draggable = marker.isDraggable(); const rotation = marker.getRotation(); const pitchAlignment = marker.getPitchAlignment(); const rotationAlignment = marker.getRotationAlignment(); root.render( ); t.is(offset, marker.getOffset(), 'offset did not change deeply'); let callbackType = ''; root.render( (callbackType = 'dragstart')} onDrag={() => (callbackType = 'drag')} onDragEnd={() => (callbackType = 'dragend')} /> ); await sleep(1); t.not(offset, marker.getOffset(), 'offset is updated'); t.not(draggable, marker.isDraggable(), 'draggable is updated'); t.not(rotation, marker.getRotation(), 'rotation is updated'); t.not(pitchAlignment, marker.getPitchAlignment(), 'pitchAlignment is updated'); t.not(rotationAlignment, marker.getRotationAlignment(), 'rotationAlignment is updated'); t.ok(marker._element.classList.contains('classA'), 'className is updated'); marker.fire('dragstart'); t.is(callbackType, 'dragstart', 'onDragStart called'); marker.fire('drag'); t.is(callbackType, 'drag', 'onDrag called'); marker.fire('dragend'); t.is(callbackType, 'dragend', 'onDragEnd called'); root.render( ); await sleep(1); t.notOk(markerRef.current, 'marker is removed'); root.render(
); await sleep(1); t.ok(rootContainer.querySelector('#marker-content'), 'content is rendered'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/components/popup.spec.jsx ================================================ import {Map, Popup} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Popup', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; const popupRef = {current: null}; root.render( You are here ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.mapboxgl-popup'), 'Popup is attached to DOM'); t.ok(popupRef.current, 'Popup is created'); const popup = popupRef.current; const {anchor, offset, maxWidth} = popup.options; root.render( ); await sleep(1); t.is(offset, popup.options.offset, 'offset did not change deeply'); t.ok(rootContainer.querySelector('#popup-content'), 'content is rendered'); root.render( ); await sleep(1); t.not(offset, popup.options.offset, 'offset is updated'); t.not(anchor, popup.options.anchor, 'anchor is updated'); t.not(maxWidth, popup.options.maxWidth, 'maxWidth is updated'); root.render( ); await sleep(1); t.ok(popup._container.classList.contains('classA'), 'className is updated'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/components/source.spec.jsx ================================================ import {Map, Source} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const geoJSON2 = { type: 'Point', coordinates: [1, 1] }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(mapRef.current.getSource('my-data'), 'Source is added'); root.render( ); await sleep(50); t.ok(mapRef.current.getSource('my-data'), 'Source is added after style change'); root.render( ); await sleep(1); const sourceData = await mapRef.current.getSource('my-data')?._data; t.deepEqual(sourceData, geoJSON2, 'Source is updated'); root.render( ); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/components/use-map.spec.jsx ================================================ import {Map, MapProvider, useMap} from '@vis.gl/react-mapbox'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import test from 'tape-promise/tape'; import {sleep, waitForMapLoad} from '../utils/test-utils'; import {MapboxAccessToken} from '../utils/token'; test('useMap', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let maps = null; function TestControl() { maps = useMap(); return null; } root.render( ); await waitForMapLoad(mapRef); t.ok(maps.mapA, 'Context has mapA'); t.ok(maps.mapB, 'Context has mapB'); root.render( ); await sleep(50); t.ok(maps.mapA, 'Context has mapA'); t.notOk(maps.mapB, 'mapB is removed'); root.render( ); await sleep(50); t.notOk(maps.mapA, 'mapA is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-mapbox/test/utils/apply-react-style.spec.js ================================================ import test from 'tape-promise/tape'; import {applyReactStyle} from '@vis.gl/react-mapbox/utils/apply-react-style'; test('applyReactStyle', t => { /* global document */ if (typeof document === 'undefined') { t.end(); return; } const div = document.createElement('div'); t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); t.is(div.style.height, '24px', 'appended px to numeric value'); t.is(div.style.lineHeight, '2', 'unitless numeric property'); t.is(div.style.zIndex, '1', 'unitless numeric property'); t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); t.end(); }); ================================================ FILE: modules/react-mapbox/test/utils/compare-class-names.spec.js ================================================ import test from 'tape-promise/tape'; import {compareClassNames} from '@vis.gl/react-mapbox/utils/compare-class-names'; test('compareClassNames', t => { const TEST_CASES = [ { title: 'Empty class names', prevClassName: '', nextClassName: '', output: null }, { title: 'Identical class names', prevClassName: 'marker active', nextClassName: 'active marker ', output: null }, { title: 'Addition', prevClassName: undefined, nextClassName: 'marker', output: ['marker'] }, { title: 'Addition', prevClassName: 'marker', nextClassName: 'marker active', output: ['active'] }, { title: 'Removal', prevClassName: 'marker active', nextClassName: 'marker', output: ['active'] }, { title: 'Multiple addition & removal', prevClassName: 'marker active', nextClassName: 'marker hovered hidden', output: ['hovered', 'hidden', 'active'] } ]; for (const testCase of TEST_CASES) { t.deepEqual( compareClassNames(testCase.prevClassName, testCase.nextClassName), testCase.output, testCase.title ); } t.end(); }); ================================================ FILE: modules/react-mapbox/test/utils/deep-equal.spec.js ================================================ import test from 'tape-promise/tape'; import {deepEqual, arePointsEqual} from '@vis.gl/react-mapbox/utils/deep-equal'; test('deepEqual', t => { const testCases = [ { a: null, b: null, result: true }, { a: undefined, b: 0, result: false }, { a: [1, 2, 3], b: [1, 2, 3], result: true }, { a: [1, 2], b: [1, 2, 3], result: false }, { a: [1, 2], b: {0: 1, 1: 2}, result: false }, { a: {x: 0, y: 0, offset: [1, -1]}, b: {x: 0, y: 0, offset: [1, -1]}, result: true }, { a: {x: 0, y: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false }, { a: {x: 0, y: 0, z: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false } ]; for (const {a, b, result} of testCases) { t.is(deepEqual(a, b), result, `${JSON.stringify(a)} vs ${JSON.stringify(b)}`); if (a !== b) { t.is(deepEqual(b, a), result, `${JSON.stringify(b)} vs ${JSON.stringify(a)}`); } } t.end(); }); test('arePointsEqual', t => { const testCases = [ { a: undefined, b: undefined, result: true }, { a: undefined, b: [0, 0], result: true }, { a: undefined, b: [0, 1], result: false }, { a: undefined, b: [1, 0], result: false }, { a: {x: 1, y: 1}, b: [1, 1], result: true } ]; for (const {a, b, result} of testCases) { t.is(arePointsEqual(a, b), result, `${JSON.stringify(a)}, ${JSON.stringify(b)}`); if (a !== b) { t.is(arePointsEqual(b, a), result, `${JSON.stringify(b)}, ${JSON.stringify(a)}`); } } t.end(); }); ================================================ FILE: modules/react-mapbox/test/utils/index.js ================================================ import './deep-equal.spec'; import './transform.spec'; import './style-utils.spec'; import './apply-react-style.spec'; import './compare-class-names.spec'; ================================================ FILE: modules/react-mapbox/test/utils/mapbox-gl-mock/edge_insets.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/edge_insets.js import Point from '@mapbox/point-geometry'; import {clamp, number} from './util.js'; class EdgeInsets { constructor(top = 0, bottom = 0, left = 0, right = 0) { if ( isNaN(top) || top < 0 || isNaN(bottom) || bottom < 0 || isNaN(left) || left < 0 || isNaN(right) || right < 0 ) { throw new Error( 'Invalid value for edge-insets, top, bottom, left and right must all be numbers' ); } this.top = top; this.bottom = bottom; this.left = left; this.right = right; } interpolate(start, target, t) { if (target.top != null && start.top != null) this.top = number(start.top, target.top, t); if (target.bottom != null && start.bottom != null) this.bottom = number(start.bottom, target.bottom, t); if (target.left != null && start.left != null) this.left = number(start.left, target.left, t); if (target.right != null && start.right != null) this.right = number(start.right, target.right, t); return this; } getCenter(width, height) { // Clamp insets so they never overflow width/height and always calculate a valid center const x = clamp((this.left + width - this.right) / 2, 0, width); const y = clamp((this.top + height - this.bottom) / 2, 0, height); return new Point(x, y); } equals(other) { return ( this.top === other.top && this.bottom === other.bottom && this.left === other.left && this.right === other.right ); } clone() { return new EdgeInsets(this.top, this.bottom, this.left, this.right); } toJSON() { return { top: this.top, bottom: this.bottom, left: this.left, right: this.right }; } } export default EdgeInsets; ================================================ FILE: modules/react-mapbox/test/utils/mapbox-gl-mock/lng_lat.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/lng_lat.js import {wrap} from './util.js'; import LngLatBounds from './lng_lat_bounds.js'; export const earthRadius = 6371008.8; class LngLat { lng; lat; constructor(lng, lat) { if (isNaN(lng) || isNaN(lat)) { throw new Error(`Invalid LngLat object: (${lng}, ${lat})`); } this.lng = Number(lng); this.lat = Number(lat); if (this.lat > 90 || this.lat < -90) { throw new Error('Invalid LngLat latitude value: must be between -90 and 90'); } } wrap() { return new LngLat(wrap(this.lng, -180, 180), this.lat); } toArray() { return [this.lng, this.lat]; } toString() { return `LngLat(${this.lng}, ${this.lat})`; } distanceTo(lngLat) { const rad = Math.PI / 180; const lat1 = this.lat * rad; const lat2 = lngLat.lat * rad; const a = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1) * Math.cos(lat2) * Math.cos((lngLat.lng - this.lng) * rad); const maxMeters = earthRadius * Math.acos(Math.min(a, 1)); return maxMeters; } toBounds(radius = 0) { const earthCircumferenceInMetersAtEquator = 40075017; const latAccuracy = (360 * radius) / earthCircumferenceInMetersAtEquator; const lngAccuracy = latAccuracy / Math.cos((Math.PI / 180) * this.lat); return new LngLatBounds( new LngLat(this.lng - lngAccuracy, this.lat - latAccuracy), new LngLat(this.lng + lngAccuracy, this.lat + latAccuracy) ); } static convert(input) { if (input instanceof LngLat) { return input; } if (Array.isArray(input) && (input.length === 2 || input.length === 3)) { return new LngLat(Number(input[0]), Number(input[1])); } if (!Array.isArray(input) && typeof input === 'object' && input !== null) { return new LngLat( // flow can't refine this to have one of lng or lat, so we have to cast to any Number('lng' in input ? input.lng : input.lon), Number(input.lat) ); } throw new Error( '`LngLatLike` argument must be specified as a LngLat instance, an object {lng: , lat: }, an object {lon: , lat: }, or an array of [, ]' ); } } export default LngLat; ================================================ FILE: modules/react-mapbox/test/utils/mapbox-gl-mock/lng_lat_bounds.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/geo/lng_lat_bounds.js import LngLat from './lng_lat.js'; class LngLatBounds { _ne; _sw; // This constructor is too flexible to type. It should not be so flexible. constructor(sw, ne) { if (!sw) { // noop } else if (ne) { this.setSouthWest(sw).setNorthEast(ne); } else if (sw.length === 4) { this.setSouthWest([sw[0], sw[1]]).setNorthEast([sw[2], sw[3]]); } else { this.setSouthWest(sw[0]).setNorthEast(sw[1]); } } setNorthEast(ne) { this._ne = ne instanceof LngLat ? new LngLat(ne.lng, ne.lat) : LngLat.convert(ne); return this; } setSouthWest(sw) { this._sw = sw instanceof LngLat ? new LngLat(sw.lng, sw.lat) : LngLat.convert(sw); return this; } extend(obj) { const sw = this._sw; const ne = this._ne; let ne2; let sw2; if (obj instanceof LngLat) { sw2 = obj; ne2 = obj; } else if (obj instanceof LngLatBounds) { sw2 = obj._sw; ne2 = obj._ne; if (!sw2 || !ne2) return this; } else { if (Array.isArray(obj)) { if (obj.length === 4 || obj.every(Array.isArray)) { const lngLatBoundsObj = obj; return this.extend(LngLatBounds.convert(lngLatBoundsObj)); } const lngLatObj = obj; return this.extend(LngLat.convert(lngLatObj)); } return this; } if (!sw && !ne) { this._sw = new LngLat(sw2.lng, sw2.lat); this._ne = new LngLat(ne2.lng, ne2.lat); } else { sw.lng = Math.min(sw2.lng, sw.lng); sw.lat = Math.min(sw2.lat, sw.lat); ne.lng = Math.max(ne2.lng, ne.lng); ne.lat = Math.max(ne2.lat, ne.lat); } return this; } getCenter() { return new LngLat((this._sw.lng + this._ne.lng) / 2, (this._sw.lat + this._ne.lat) / 2); } getSouthWest() { return this._sw; } getNorthEast() { return this._ne; } getNorthWest() { return new LngLat(this.getWest(), this.getNorth()); } getSouthEast() { return new LngLat(this.getEast(), this.getSouth()); } getWest() { return this._sw.lng; } getSouth() { return this._sw.lat; } getEast() { return this._ne.lng; } getNorth() { return this._ne.lat; } toArray() { return [this._sw.toArray(), this._ne.toArray()]; } toString() { return `LngLatBounds(${this._sw.toString()}, ${this._ne.toString()})`; } isEmpty() { return !(this._sw && this._ne); } contains(lnglat) { const {lng, lat} = LngLat.convert(lnglat); const containsLatitude = this._sw.lat <= lat && lat <= this._ne.lat; let containsLongitude = this._sw.lng <= lng && lng <= this._ne.lng; if (this._sw.lng > this._ne.lng) { // wrapped coordinates containsLongitude = this._sw.lng >= lng && lng >= this._ne.lng; } return containsLatitude && containsLongitude; } static convert(input) { if (!input || input instanceof LngLatBounds) return input; return new LngLatBounds(input); } } export default LngLatBounds; ================================================ FILE: modules/react-mapbox/test/utils/mapbox-gl-mock/transform.js ================================================ import {wrap, clamp} from './util'; import LngLat from './lng_lat'; import EdgeInsets from './edge_insets'; export default class Transform { constructor() { this.minZoom = 0; this.maxZoom = 22; this.minPitch = 0; this.maxPitch = 60; this.minLat = -85.051129; this.maxLat = 85.051129; this.minLng = -180; this.maxLng = 180; this.width = 1; this.height = 1; this._center = new LngLat(0, 0); this._zoom = 0; this.angle = 0; this._pitch = 0; this._edgeInsets = new EdgeInsets(); this._centerAltitude = 0; } get bearing() { return wrap(this.rotation, -180, 180); } set bearing(bearing) { this.rotation = bearing; } get rotation() { return (-this.angle / Math.PI) * 180; } set rotation(rotation) { const b = (-rotation * Math.PI) / 180; if (this.angle === b) return; this.angle = b; } get pitch() { return (this._pitch / Math.PI) * 180; } set pitch(pitch) { const p = (clamp(pitch, this.minPitch, this.maxPitch) / 180) * Math.PI; if (this._pitch === p) return; this._pitch = p; } get zoom() { return this._zoom; } set zoom(zoom) { const z = Math.min(Math.max(zoom, this.minZoom), this.maxZoom); if (this._zoom === z) return; this._zoom = z; } get center() { return this._center; } set center(center) { if (center.lat === this._center.lat && center.lng === this._center.lng) return; this._center = center; } get padding() { return this._edgeInsets.toJSON(); } set padding(padding) { if (this._edgeInsets.equals(padding)) return; // Update edge-insets inplace this._edgeInsets.interpolate(this._edgeInsets, padding, 1); } clone() { const that = new Transform(); that.center = this.center; that.zoom = this.zoom; that.bearing = this.bearing; that.pitch = this.pitch; that.padding = this.padding; return that; } isPaddingEqual(padding) { return this._edgeInsets.equals(padding); } _constrain() {} _calcMatrices() {} } ================================================ FILE: modules/react-mapbox/test/utils/mapbox-gl-mock/util.js ================================================ // Generated with // flow-remove-types ./node_modules/mapbox-gl/src/util/util.js export function clamp(n, min, max) { return Math.min(max, Math.max(min, n)); } export function wrap(n, min, max) { const d = max - min; const w = ((((n - min) % d) + d) % d) + min; return w === min ? max : w; } export function extend(dest, ...sources) { for (const src of sources) { for (const k in src) { dest[k] = src[k]; } } return dest; } export function number(a, b, t) { return a * (1 - t) + b * t; } ================================================ FILE: modules/react-mapbox/test/utils/style-utils.spec.js ================================================ import test from 'tape-promise/tape'; import {normalizeStyle} from '@vis.gl/react-mapbox/utils/style-utils'; const testStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 }, interactive: true }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20, interactive: true }, { id: 'park-2', ref: 'park', paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', ref: 'road', minzoom: 10, maxzoom: 12, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; const expectedStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 } }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20 }, { id: 'park-2', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', minzoom: 5, maxzoom: 20, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; test('normalizeStyle', t => { // Make sure the style is not mutated freezeRecursive(testStyle); t.is(normalizeStyle(null), null, 'Handles null'); t.is( normalizeStyle('mapbox://styles/mapbox/light-v9'), 'mapbox://styles/mapbox/light-v9', 'Handles url string' ); let result = normalizeStyle(testStyle); t.notEqual(result, testStyle, 'style is not mutated'); t.deepEqual(result, expectedStyle, 'plain object style is normalized'); // Immutable-like object result = normalizeStyle({toJS: () => testStyle}); t.deepEqual(result, expectedStyle, 'immutable style is normalized'); t.end(); }); function freezeRecursive(obj) { if (!obj) return; if (typeof obj === 'object') { if (Array.isArray(obj)) { for (const el of obj) { freezeRecursive(el); } } else { for (const key in obj) { freezeRecursive(obj[key]); } } Object.freeze(obj); } } ================================================ FILE: modules/react-mapbox/test/utils/test-utils.jsx ================================================ /* global setTimeout */ export function sleep(milliseconds) { return new Promise(resolve => setTimeout(resolve, milliseconds)); } export function waitForMapLoad(mapRef) { return new Promise(resolve => { const check = () => { if (mapRef.current && mapRef.current.getMap().isStyleLoaded()) { resolve(); } else { setTimeout(check, 50); } }; check(); }); } ================================================ FILE: modules/react-mapbox/test/utils/token.js ================================================ export const MapboxAccessToken = import.meta.env.VITE_MAPBOX_TOKEN; ================================================ FILE: modules/react-mapbox/test/utils/transform.spec.js ================================================ import test from 'tape-promise/tape'; import { transformToViewState, compareViewStateWithTransform, applyViewStateToTransform } from '@vis.gl/react-mapbox/utils/transform'; import Transform from './mapbox-gl-mock/transform'; test('applyViewStateToTransform', t => { const tr = new Transform(); let viewState = {}; let changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.notOk(changed, 'empty view state'); viewState = {longitude: -10, latitude: 5}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'center changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 0, pitch: 0, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0}, elevation: 0 }, 'view state is correct' ); viewState = {zoom: 10}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'zoom changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 0, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0}, elevation: 0 }, 'view state is correct' ); viewState = {pitch: 30}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'pitch changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: 0, padding: {left: 0, right: 0, top: 0, bottom: 0}, elevation: 0 }, 'view state is correct' ); viewState = {bearing: 270}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'bearing changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: -90, padding: {left: 0, right: 0, top: 0, bottom: 0}, elevation: 0 }, 'view state is correct' ); viewState = {padding: {left: 10, right: 10, top: 10, bottom: 10}}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'padding changed'); t.deepEqual( transformToViewState(tr), { longitude: -10, latitude: 5, zoom: 10, pitch: 30, bearing: -90, padding: {left: 10, right: 10, top: 10, bottom: 10}, elevation: 0 }, 'view state is correct' ); viewState = {pitch: 30}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.notOk(changed, 'nothing changed'); applyViewStateToTransform(tr, {longitude: 0, latitude: 0, zoom: 0}); viewState = {longitude: 12, latitude: 34, zoom: 15}; changed = compareViewStateWithTransform(tr, viewState); applyViewStateToTransform(tr, viewState); t.ok(changed, 'center and zoom changed'); t.equal(tr.zoom, 15, 'zoom is correct'); t.equal(tr.center.lat, 34, 'center latitude is correct'); t.end(); }); ================================================ FILE: modules/react-mapbox/tsconfig.json ================================================ { "extends": "../../tsconfig.json", "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { "composite": true, "rootDir": "src", "outDir": "dist" }, "references": [ ] } ================================================ FILE: modules/react-maplibre/package.json ================================================ { "name": "@vis.gl/react-maplibre", "description": "React components for Maplibre GL JS", "version": "8.1.0-alpha.2", "keywords": [ "maplibre", "maplibre-gl", "react", "react maplibre" ], "repository": { "type": "git", "url": "https://github.com/visgl/react-map-gl.git" }, "license": "MIT", "type": "module", "types": "dist/index.d.ts", "main": "dist/index.cjs", "module": "dist/index.js", "exports": { ".": { "import": "./dist/index.js", "require": "./dist/index.cjs", "types": "./dist/index.d.ts" } }, "files": [ "src", "dist", "README.md" ], "dependencies": { "@maplibre/maplibre-gl-style-spec": "^19.2.1" }, "devDependencies": { "maplibre-gl": "^5.0.0" }, "peerDependencies": { "maplibre-gl": ">=4.0.0", "react": ">=16.3.0", "react-dom": ">=16.3.0" }, "peerDependenciesMeta": { "maplibre-gl": { "optional": true } } } ================================================ FILE: modules/react-maplibre/src/components/attribution-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, AttributionControlOptions} from '../types/lib'; export type AttributionControlProps = AttributionControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _AttributionControl(props: AttributionControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.AttributionControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const AttributionControl = memo(_AttributionControl); ================================================ FILE: modules/react-maplibre/src/components/fullscreen-control.ts ================================================ /* global document */ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, FullscreenControlOptions} from '../types/lib'; export type FullscreenControlProps = Omit & { /** Id of the DOM element which should be made full screen. By default, the map container * element will be made full screen. */ containerId?: string; /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _FullscreenControl(props: FullscreenControlProps) { const ctrl = useControl( ({mapLib}) => new mapLib.FullscreenControl({ container: props.containerId && document.getElementById(props.containerId) }), {position: props.position} ); useEffect(() => { applyReactStyle(ctrl._controlContainer, props.style); }, [props.style]); return null; } export const FullscreenControl = memo(_FullscreenControl); ================================================ FILE: modules/react-maplibre/src/components/geolocate-control.ts ================================================ import * as React from 'react'; import {useImperativeHandle, useRef, useEffect, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type { ControlPosition, GeolocateControlInstance, GeolocateControlOptions } from '../types/lib'; import type {GeolocateEvent, GeolocateResultEvent, GeolocateErrorEvent} from '../types/events'; export type GeolocateControlProps = GeolocateControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; /** Called on each Geolocation API position update that returned as success. */ onGeolocate?: (e: GeolocateResultEvent) => void; /** Called on each Geolocation API position update that returned as an error. */ onError?: (e: GeolocateErrorEvent) => void; /** Called on each Geolocation API position update that returned as success but user position * is out of map `maxBounds`. */ onOutOfMaxBounds?: (e: GeolocateResultEvent) => void; /** Called when the GeolocateControl changes to the active lock state. */ onTrackUserLocationStart?: (e: GeolocateEvent) => void; /** Called when the GeolocateControl changes to the background state. */ onTrackUserLocationEnd?: (e: GeolocateEvent) => void; }; function _GeolocateControl(props: GeolocateControlProps, ref: React.Ref) { const thisRef = useRef({props}); const ctrl = useControl( ({mapLib}) => { const gc = new mapLib.GeolocateControl(props); // Hack: fix GeolocateControl reuse // When using React strict mode, the component is mounted twice. // GeolocateControl's UI creation is asynchronous. Removing and adding it back causes the UI to be initialized twice. const setupUI = gc._setupUI; gc._setupUI = () => { if (!gc._container.hasChildNodes()) { setupUI(); } }; gc.on('geolocate', e => { thisRef.current.props.onGeolocate?.(e as GeolocateResultEvent); }); gc.on('error', e => { thisRef.current.props.onError?.(e as GeolocateErrorEvent); }); gc.on('outofmaxbounds', e => { thisRef.current.props.onOutOfMaxBounds?.(e as GeolocateResultEvent); }); gc.on('trackuserlocationstart', e => { thisRef.current.props.onTrackUserLocationStart?.(e as GeolocateEvent); }); gc.on('trackuserlocationend', e => { thisRef.current.props.onTrackUserLocationEnd?.(e as GeolocateEvent); }); return gc; }, {position: props.position} ); thisRef.current.props = props; useImperativeHandle(ref, () => ctrl, []); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const GeolocateControl = memo(forwardRef(_GeolocateControl)); ================================================ FILE: modules/react-maplibre/src/components/globe-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import {ControlPosition} from '../types/lib'; export type GlobeControlProps = { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _GlobeControl(props: GlobeControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.GlobeControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const GlobeControl = memo(_GlobeControl); ================================================ FILE: modules/react-maplibre/src/components/layer.ts ================================================ import {useContext, useEffect, useMemo, useState, useRef} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type {MapInstance, CustomLayerInterface} from '../types/lib'; import type {LayerSpecification} from '../types/style-spec'; // Omiting property from a union type, see // https://github.com/microsoft/TypeScript/issues/39556#issuecomment-656925230 type OptionalId = T extends {id: string} ? Omit & {id?: string} : T; type OptionalSource = T extends {source: string} ? Omit & {source?: string} : T; export type LayerProps = (OptionalSource> | CustomLayerInterface) & { /** If set, the layer will be inserted before the specified layer */ beforeId?: string; }; /* eslint-disable complexity, max-statements */ function updateLayer(map: MapInstance, id: string, props: LayerProps, prevProps: LayerProps) { assert(props.id === prevProps.id, 'layer id changed'); assert(props.type === prevProps.type, 'layer type changed'); if (props.type === 'custom' || prevProps.type === 'custom') { return; } // @ts-ignore filter does not exist in some Layer types const {layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId} = props; if (beforeId !== prevProps.beforeId) { map.moveLayer(id, beforeId); } if (layout !== prevProps.layout) { const prevLayout = prevProps.layout || {}; for (const key in layout) { if (!deepEqual(layout[key], prevLayout[key])) { map.setLayoutProperty(id, key, layout[key]); } } for (const key in prevLayout) { if (!layout.hasOwnProperty(key)) { map.setLayoutProperty(id, key, undefined); } } } if (paint !== prevProps.paint) { const prevPaint = prevProps.paint || {}; for (const key in paint) { if (!deepEqual(paint[key], prevPaint[key])) { map.setPaintProperty(id, key, paint[key]); } } for (const key in prevPaint) { if (!paint.hasOwnProperty(key)) { map.setPaintProperty(id, key, undefined); } } } // @ts-ignore filter does not exist in some Layer types if (!deepEqual(filter, prevProps.filter)) { map.setFilter(id, filter); } if (minzoom !== prevProps.minzoom || maxzoom !== prevProps.maxzoom) { map.setLayerZoomRange(id, minzoom, maxzoom); } } function createLayer(map: MapInstance, id: string, props: LayerProps) { // @ts-ignore if (map.style && map.style._loaded && (!('source' in props) || map.getSource(props.source))) { const options: LayerProps = {...props, id}; delete options.beforeId; // @ts-ignore map.addLayer(options, props.beforeId); } } /* eslint-enable complexity, max-statements */ let layerCounter = 0; export function Layer(props: LayerProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-layer-${layerCounter++}`, []); useEffect(() => { if (map) { const forceUpdate = () => setStyleLoaded(version => version + 1); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getLayer(id)) { map.removeLayer(id); } }; } return undefined; }, [map]); // @ts-ignore const layer = map && map.style && map.getLayer(id); if (layer) { try { updateLayer(map, id, props, propsRef.current); } catch (error) { console.warn(error); // eslint-disable-line } } else { createLayer(map, id, props); } // Store last rendered props propsRef.current = props; return null; } ================================================ FILE: modules/react-maplibre/src/components/logo-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, LogoControlOptions} from '../types/lib'; export type LogoControlProps = LogoControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _LogoControl(props: LogoControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.LogoControl(props), {position: props.position}); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const LogoControl = memo(_LogoControl); ================================================ FILE: modules/react-maplibre/src/components/map.tsx ================================================ import * as React from 'react'; import {useState, useRef, useEffect, useContext, useMemo, useImperativeHandle} from 'react'; import {MountedMapsContext} from './use-map'; import Maplibre, {MaplibreProps} from '../maplibre/maplibre'; import createRef, {MapRef} from '../maplibre/create-ref'; import type {CSSProperties} from 'react'; import useIsomorphicLayoutEffect from '../utils/use-isomorphic-layout-effect'; import setGlobals, {GlobalSettings} from '../utils/set-globals'; import type {MapLib, MapOptions} from '../types/lib'; export type MapContextValue = { mapLib: MapLib; map: MapRef; }; export const MapContext = React.createContext(null); type MapInitOptions = Omit< MapOptions, 'style' | 'container' | 'bounds' | 'fitBoundsOptions' | 'center' >; export type MapProps = MapInitOptions & MaplibreProps & GlobalSettings & { mapLib?: MapLib | Promise; reuseMaps?: boolean; /** Map container id */ id?: string; /** Map container CSS style */ style?: CSSProperties; children?: any; }; function _Map(props: MapProps, ref: React.Ref) { const mountedMapsContext = useContext(MountedMapsContext); const [mapInstance, setMapInstance] = useState(null); const containerRef = useRef(); const {current: contextValue} = useRef({mapLib: null, map: null}); useEffect(() => { const mapLib = props.mapLib; let isMounted = true; let maplibre: Maplibre; Promise.resolve(mapLib || import('maplibre-gl')) .then((module: MapLib | {default: MapLib}) => { if (!isMounted) { return; } if (!module) { throw new Error('Invalid mapLib'); } const mapboxgl = 'Map' in module ? module : module.default; if (!mapboxgl.Map) { throw new Error('Invalid mapLib'); } setGlobals(mapboxgl, props); if (props.reuseMaps) { maplibre = Maplibre.reuse(props, containerRef.current); } if (!maplibre) { maplibre = new Maplibre(mapboxgl.Map, props, containerRef.current); } contextValue.map = createRef(maplibre); contextValue.mapLib = mapboxgl; setMapInstance(maplibre); mountedMapsContext?.onMapMount(contextValue.map, props.id); }) .catch(error => { const {onError} = props; if (onError) { onError({ type: 'error', target: null, originalEvent: null, error }); } else { console.error(error); // eslint-disable-line } }); return () => { isMounted = false; if (maplibre) { mountedMapsContext?.onMapUnmount(props.id); if (props.reuseMaps) { maplibre.recycle(); } else { maplibre.destroy(); } } }; }, []); useIsomorphicLayoutEffect(() => { if (mapInstance) { mapInstance.setProps(props); } }); useImperativeHandle(ref, () => contextValue.map, [mapInstance]); const style: CSSProperties = useMemo( () => ({ position: 'relative', width: '100%', height: '100%', ...props.style }), [props.style] ); const CHILD_CONTAINER_STYLE = { height: '100%' }; return (
{mapInstance && (
{props.children}
)}
); } export const Map = React.forwardRef(_Map); ================================================ FILE: modules/react-maplibre/src/components/marker.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance, MarkerInstance, MarkerOptions} from '../types/lib'; import type {MarkerEvent, MarkerDragEvent} from '../types/events'; import {MapContext} from './map'; import {arePointsEqual} from '../utils/deep-equal'; import {compareClassNames} from '../utils/compare-class-names'; export type MarkerProps = MarkerOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; popup?: PopupInstance; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onClick?: (e: MarkerEvent) => void; onDragStart?: (e: MarkerDragEvent) => void; onDrag?: (e: MarkerDragEvent) => void; onDragEnd?: (e: MarkerDragEvent) => void; children?: React.ReactNode; }; /* eslint-disable complexity,max-statements */ export const Marker = memo( forwardRef((props: MarkerProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const thisRef = useRef({props}); const marker: MarkerInstance = useMemo(() => { let hasChildren = false; React.Children.forEach(props.children, el => { if (el) { hasChildren = true; } }); const options = { ...props, element: hasChildren ? document.createElement('div') : undefined }; const mk = new mapLib.Marker(options); mk.setLngLat([props.longitude, props.latitude]); mk.getElement().addEventListener('click', (e: MouseEvent) => { thisRef.current.props.onClick?.({ type: 'click', target: mk, originalEvent: e }); }); mk.on('dragstart', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragStart?.(evt); }); mk.on('drag', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDrag?.(evt); }); mk.on('dragend', e => { const evt = e as MarkerDragEvent; evt.lngLat = marker.getLngLat(); thisRef.current.props.onDragEnd?.(evt); }); return mk; }, []); useEffect(() => { marker.addTo(map.getMap()); return () => { marker.remove(); }; }, []); const { longitude, latitude, offset, style, draggable = false, popup = null, rotation = 0, rotationAlignment = 'auto', pitchAlignment = 'auto' } = props; useEffect(() => { applyReactStyle(marker.getElement(), style); }, [style]); useImperativeHandle(ref, () => marker, []); const oldProps = thisRef.current.props; if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) { marker.setLngLat([longitude, latitude]); } if (offset && !arePointsEqual(marker.getOffset(), offset)) { marker.setOffset(offset); } if (marker.isDraggable() !== draggable) { marker.setDraggable(draggable); } if (marker.getRotation() !== rotation) { marker.setRotation(rotation); } if (marker.getRotationAlignment() !== rotationAlignment) { marker.setRotationAlignment(rotationAlignment); } if (marker.getPitchAlignment() !== pitchAlignment) { marker.setPitchAlignment(pitchAlignment); } if (marker.getPopup() !== popup) { marker.setPopup(popup); } const classNameDiff = compareClassNames(oldProps.className, props.className); if (classNameDiff) { for (const c of classNameDiff) { marker.toggleClassName(c); } } thisRef.current.props = props; return createPortal(props.children, marker.getElement()); }) ); ================================================ FILE: modules/react-maplibre/src/components/navigation-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, NavigationControlOptions} from '../types/lib'; export type NavigationControlProps = NavigationControlOptions & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _NavigationControl(props: NavigationControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.NavigationControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const NavigationControl = memo(_NavigationControl); ================================================ FILE: modules/react-maplibre/src/components/popup.ts ================================================ /* global document */ import * as React from 'react'; import {createPortal} from 'react-dom'; import {useImperativeHandle, useEffect, useMemo, useRef, useContext, forwardRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import type {PopupInstance, PopupOptions} from '../types/lib'; import type {PopupEvent} from '../types/events'; import {MapContext} from './map'; import {deepEqual} from '../utils/deep-equal'; import {compareClassNames} from '../utils/compare-class-names'; export type PopupProps = PopupOptions & { /** Longitude of the anchor location */ longitude: number; /** Latitude of the anchor location */ latitude: number; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; onOpen?: (e: PopupEvent) => void; onClose?: (e: PopupEvent) => void; children?: React.ReactNode; }; /* eslint-disable complexity,max-statements */ export const Popup = memo( forwardRef((props: PopupProps, ref: React.Ref) => { const {map, mapLib} = useContext(MapContext); const container = useMemo(() => { return document.createElement('div'); }, []); const thisRef = useRef({props}); const popup: PopupInstance = useMemo(() => { const options = {...props}; const pp = new mapLib.Popup(options); pp.setLngLat([props.longitude, props.latitude]); pp.once('open', e => { thisRef.current.props.onOpen?.(e as PopupEvent); }); return pp; }, []); useEffect(() => { const onClose = e => { thisRef.current.props.onClose?.(e as PopupEvent); }; popup.on('close', onClose); popup.setDOMContent(container).addTo(map.getMap()); return () => { // https://github.com/visgl/react-map-gl/issues/1825 // onClose should not be fired if the popup is removed by unmounting // When using React strict mode, the component is mounted twice. // Firing the onClose callback here would be a false signal to remove the component. popup.off('close', onClose); if (popup.isOpen()) { popup.remove(); } }; }, []); useEffect(() => { applyReactStyle(popup.getElement(), props.style); }, [props.style]); useImperativeHandle(ref, () => popup, []); if (popup.isOpen()) { const oldProps = thisRef.current.props; if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) { popup.setLngLat([props.longitude, props.latitude]); } if (props.offset && !deepEqual(oldProps.offset, props.offset)) { popup.setOffset(props.offset); } if (oldProps.anchor !== props.anchor || oldProps.maxWidth !== props.maxWidth) { popup.options.anchor = props.anchor; popup.setMaxWidth(props.maxWidth); } const classNameDiff = compareClassNames(oldProps.className, props.className); if (classNameDiff) { for (const c of classNameDiff) { popup.toggleClassName(c); } } thisRef.current.props = props; } return createPortal(props.children, container); }) ); ================================================ FILE: modules/react-maplibre/src/components/scale-control.ts ================================================ import * as React from 'react'; import {useEffect, useRef, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition, ScaleControlOptions} from '../types/lib'; export type ScaleControlProps = ScaleControlOptions & { // These props will be further constraint by OptionsT unit?: string; maxWidth?: number; /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _ScaleControl(props: ScaleControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.ScaleControl(props), { position: props.position }); const propsRef = useRef(props); const prevProps = propsRef.current; propsRef.current = props; const {style} = props; if (props.maxWidth !== undefined && props.maxWidth !== prevProps.maxWidth) { ctrl.options.maxWidth = props.maxWidth; } if (props.unit !== undefined && props.unit !== prevProps.unit) { ctrl.setUnit(props.unit); } useEffect(() => { applyReactStyle(ctrl._container, style); }, [style]); return null; } export const ScaleControl = memo(_ScaleControl); ================================================ FILE: modules/react-maplibre/src/components/source.ts ================================================ import * as React from 'react'; import {useContext, useEffect, useMemo, useState, useRef, cloneElement} from 'react'; import {MapContext} from './map'; import assert from '../utils/assert'; import {deepEqual} from '../utils/deep-equal'; import type { GeoJSONSourceImplementation, ImageSourceImplementation, AnySourceImplementation } from '../types/internal'; import type {SourceSpecification} from '../types/style-spec'; import type {MapInstance} from '../types/lib'; export type SourceProps = SourceSpecification & { id?: string; children?: any; }; let sourceCounter = 0; function createSource(map: MapInstance, id: string, props: SourceProps) { // @ts-ignore if (map.style && map.style._loaded) { const options = {...props}; delete options.id; delete options.children; // @ts-ignore map.addSource(id, options); return map.getSource(id); } return null; } /* eslint-disable complexity */ function updateSource(source: AnySourceImplementation, props: SourceProps, prevProps: SourceProps) { assert(props.id === prevProps.id, 'source id changed'); assert(props.type === prevProps.type, 'source type changed'); let changedKey = ''; let changedKeyCount = 0; for (const key in props) { if (key !== 'children' && key !== 'id' && !deepEqual(prevProps[key], props[key])) { changedKey = key; changedKeyCount++; } } if (!changedKeyCount) { return; } const type = props.type; if (type === 'geojson') { (source as GeoJSONSourceImplementation).setData(props.data); } else if (type === 'image') { (source as ImageSourceImplementation).updateImage({ url: props.url, coordinates: props.coordinates }); } else { switch (changedKey) { case 'coordinates': // @ts-ignore source.setCoordinates?.(props.coordinates); break; case 'url': // @ts-ignore source.setUrl?.(props.url); break; case 'tiles': // @ts-ignore source.setTiles?.(props.tiles); break; default: // eslint-disable-next-line console.warn(`Unable to update prop: ${changedKey}`); } } } /* eslint-enable complexity */ export function Source(props: SourceProps) { const map = useContext(MapContext).map.getMap(); const propsRef = useRef(props); const [, setStyleLoaded] = useState(0); const id = useMemo(() => props.id || `jsx-source-${sourceCounter++}`, []); useEffect(() => { if (map) { /* global setTimeout */ const forceUpdate = () => setTimeout(() => setStyleLoaded(version => version + 1), 0); map.on('styledata', forceUpdate); forceUpdate(); return () => { map.off('styledata', forceUpdate); // @ts-ignore if (map.style && map.style._loaded && map.getSource(id)) { // Parent effects are destroyed before child ones, see // https://github.com/facebook/react/issues/16728 // Source can only be removed after all child layers are removed const allLayers = map.getStyle()?.layers; if (allLayers) { for (const layer of allLayers) { // @ts-ignore (2339) source does not exist on all layer types if (layer.source === id) { map.removeLayer(layer.id); } } } map.removeSource(id); } }; } return undefined; }, [map]); // @ts-ignore let source = map && map.style && map.getSource(id); if (source) { updateSource(source, props, propsRef.current); } else { source = createSource(map, id, props); } propsRef.current = props; return ( (source && React.Children.map( props.children, child => child && cloneElement(child, { source: id }) )) || null ); } ================================================ FILE: modules/react-maplibre/src/components/terrain-control.ts ================================================ import * as React from 'react'; import {useEffect, memo} from 'react'; import {applyReactStyle} from '../utils/apply-react-style'; import {useControl} from './use-control'; import type {ControlPosition} from '../types/lib'; import type {TerrainSpecification} from '../types/style-spec'; export type TerrainControlProps = TerrainSpecification & { /** Placement of the control relative to the map. */ position?: ControlPosition; /** CSS style override, applied to the control's container */ style?: React.CSSProperties; }; function _TerrainControl(props: TerrainControlProps) { const ctrl = useControl(({mapLib}) => new mapLib.TerrainControl(props), { position: props.position }); useEffect(() => { applyReactStyle(ctrl._container, props.style); }, [props.style]); return null; } export const TerrainControl = memo(_TerrainControl); ================================================ FILE: modules/react-maplibre/src/components/use-control.ts ================================================ import {useContext, useMemo, useEffect} from 'react'; import type {IControl, ControlPosition} from '../types/lib'; import {MapContext} from './map'; import type {MapContextValue} from './map'; type ControlOptions = { position?: ControlPosition; }; export function useControl( onCreate: (context: MapContextValue) => T, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, onAdd: (context: MapContextValue) => void, onRemove: (context: MapContextValue) => void, opts?: ControlOptions ): T; export function useControl( onCreate: (context: MapContextValue) => T, arg1?: ((context: MapContextValue) => void) | ControlOptions, arg2?: ((context: MapContextValue) => void) | ControlOptions, arg3?: ControlOptions ): T { const context = useContext(MapContext); const ctrl = useMemo(() => onCreate(context), []); useEffect(() => { const opts = (arg3 || arg2 || arg1) as ControlOptions; const onAdd = typeof arg1 === 'function' && typeof arg2 === 'function' ? arg1 : null; const onRemove = typeof arg2 === 'function' ? arg2 : typeof arg1 === 'function' ? arg1 : null; const {map} = context; if (!map.hasControl(ctrl)) { map.addControl(ctrl, opts?.position); if (onAdd) { onAdd(context); } } return () => { if (onRemove) { onRemove(context); } // Map might have been removed (parent effects are destroyed before child ones) if (map.hasControl(ctrl)) { map.removeControl(ctrl); } }; }, []); return ctrl; } ================================================ FILE: modules/react-maplibre/src/components/use-map.tsx ================================================ import * as React from 'react'; import {useState, useCallback, useMemo, useContext} from 'react'; import {MapRef} from '../maplibre/create-ref'; import {MapContext} from './map'; type MountedMapsContextValue = { maps: {[id: string]: MapRef}; onMapMount: (map: MapRef, id: string) => void; onMapUnmount: (id: string) => void; }; export const MountedMapsContext = React.createContext(null); export const MapProvider: React.FC<{children?: React.ReactNode}> = props => { const [maps, setMaps] = useState<{[id: string]: MapRef}>({}); const onMapMount = useCallback((map: MapRef, id: string = 'default') => { setMaps(currMaps => { if (id === 'current') { throw new Error("'current' cannot be used as map id"); } if (currMaps[id]) { throw new Error(`Multiple maps with the same id: ${id}`); } return {...currMaps, [id]: map}; }); }, []); const onMapUnmount = useCallback((id: string = 'default') => { setMaps(currMaps => { if (currMaps[id]) { const nextMaps = {...currMaps}; delete nextMaps[id]; return nextMaps; } return currMaps; }); }, []); return ( {props.children} ); }; export type MapCollection = { [id: string]: MapRef | undefined; current?: MapRef; }; export function useMap(): MapCollection { const maps = useContext(MountedMapsContext)?.maps; const currentMap = useContext(MapContext); const mapsWithCurrent = useMemo(() => { return {...maps, current: currentMap?.map}; }, [maps, currentMap]); return mapsWithCurrent as MapCollection; } ================================================ FILE: modules/react-maplibre/src/index.ts ================================================ import {Map} from './components/map'; export {Map}; export default Map; export {Marker} from './components/marker'; export {Popup} from './components/popup'; export {AttributionControl} from './components/attribution-control'; export {FullscreenControl} from './components/fullscreen-control'; export {GeolocateControl} from './components/geolocate-control'; export {NavigationControl} from './components/navigation-control'; export {ScaleControl} from './components/scale-control'; export {TerrainControl} from './components/terrain-control'; export {LogoControl} from './components/logo-control'; export {Source} from './components/source'; export {Layer} from './components/layer'; export {useControl} from './components/use-control'; export {MapProvider, useMap} from './components/use-map'; export type {MapProps} from './components/map'; export type {MapRef} from './maplibre/create-ref'; export type {MarkerProps} from './components/marker'; export type {PopupProps} from './components/popup'; export type {AttributionControlProps} from './components/attribution-control'; export type {FullscreenControlProps} from './components/fullscreen-control'; export type {GeolocateControlProps} from './components/geolocate-control'; export type {NavigationControlProps} from './components/navigation-control'; export type {ScaleControlProps} from './components/scale-control'; export type {TerrainControlProps} from './components/terrain-control'; export type {LogoControlProps} from './components/logo-control'; export type {SourceProps} from './components/source'; export type {LayerProps} from './components/layer'; // Types export * from './types/common'; export * from './types/events'; export * from './types/lib'; export * from './types/style-spec'; ================================================ FILE: modules/react-maplibre/src/maplibre/create-ref.ts ================================================ import type {MapInstance} from '../types/lib'; import type Maplibre from './maplibre'; /** These methods may break the react binding if called directly */ const skipMethods = [ 'setMaxBounds', 'setMinZoom', 'setMaxZoom', 'setMinPitch', 'setMaxPitch', 'setRenderWorldCopies', 'setProjection', 'setStyle', 'addSource', 'removeSource', 'addLayer', 'removeLayer', 'setLayerZoomRange', 'setFilter', 'setPaintProperty', 'setLayoutProperty', 'setLight', 'setTerrain', 'setFog', 'remove' ] as const; export type MapRef = { getMap(): MapInstance; } & Omit; export default function createRef(mapInstance: Maplibre): MapRef | null { if (!mapInstance) { return null; } const map = mapInstance.map; const result: any = { getMap: () => map }; for (const key of getMethodNames(map)) { // @ts-expect-error if (!(key in result) && !skipMethods.includes(key)) { result[key] = map[key].bind(map); } } return result; } function getMethodNames(obj: Object) { const result = new Set(); let proto = obj; while (proto) { for (const key of Object.getOwnPropertyNames(proto)) { if ( key[0] !== '_' && typeof obj[key] === 'function' && key !== 'fire' && key !== 'setEventedParent' ) { result.add(key); } } proto = Object.getPrototypeOf(proto); } return Array.from(result); } ================================================ FILE: modules/react-maplibre/src/maplibre/maplibre.ts ================================================ import {transformToViewState, applyViewStateToTransform} from '../utils/transform'; import {normalizeStyle} from '../utils/style-utils'; import {deepEqual} from '../utils/deep-equal'; import type {TransformLike} from '../types/internal'; import type { ViewState, Point, PointLike, PaddingOptions, ImmutableLike, LngLatBoundsLike, MapGeoJSONFeature } from '../types/common'; import type { StyleSpecification, SkySpecification, LightSpecification, TerrainSpecification, ProjectionSpecification } from '../types/style-spec'; import type {MapInstance} from '../types/lib'; import type { MapCallbacks, ViewStateChangeEvent, MapEvent, ErrorEvent, MapMouseEvent } from '../types/events'; export type MaplibreProps = Partial & MapCallbacks & { /** Camera options used when constructing the Map instance */ initialViewState?: Partial & { /** The initial bounds of the map. If bounds is specified, it overrides longitude, latitude and zoom options. */ bounds?: LngLatBoundsLike; /** A fitBounds options object to use only when setting the bounds option. */ fitBoundsOptions?: { offset?: PointLike; minZoom?: number; maxZoom?: number; padding?: number | PaddingOptions; }; }; /** If provided, render into an external WebGL context */ gl?: WebGLRenderingContext; /** For external controller to override the camera state */ viewState?: ViewState & { width: number; height: number; }; // Styling /** Mapbox style */ mapStyle?: string | StyleSpecification | ImmutableLike; /** Enable diffing when the map style changes * @default true */ styleDiffing?: boolean; /** The projection property of the style. Must conform to the Projection Style Specification. * @default 'mercator' */ projection?: ProjectionSpecification | 'mercator' | 'globe'; /** Light properties of the map. */ light?: LightSpecification; /** Terrain property of the style. Must conform to the Terrain Style Specification. * If `undefined` is provided, removes terrain from the map. */ terrain?: TerrainSpecification; /** Sky properties of the map. Must conform to the Sky Style Specification. */ sky?: SkySpecification; /** Default layers to query on pointer events */ interactiveLayerIds?: string[]; /** CSS cursor */ cursor?: string; }; const DEFAULT_STYLE = {version: 8, sources: {}, layers: []} as StyleSpecification; const DEFAULT_SETTINGS = { minZoom: 0, maxZoom: 22, minPitch: 0, maxPitch: 85, maxBounds: [-180, -85.051129, 180, 85.051129], projection: 'mercator', renderWorldCopies: true }; const pointerEvents = { mousedown: 'onMouseDown', mouseup: 'onMouseUp', mouseover: 'onMouseOver', mousemove: 'onMouseMove', click: 'onClick', dblclick: 'onDblClick', mouseenter: 'onMouseEnter', mouseleave: 'onMouseLeave', mouseout: 'onMouseOut', contextmenu: 'onContextMenu', touchstart: 'onTouchStart', touchend: 'onTouchEnd', touchmove: 'onTouchMove', touchcancel: 'onTouchCancel' }; const cameraEvents = { movestart: 'onMoveStart', move: 'onMove', moveend: 'onMoveEnd', dragstart: 'onDragStart', drag: 'onDrag', dragend: 'onDragEnd', zoomstart: 'onZoomStart', zoom: 'onZoom', zoomend: 'onZoomEnd', rotatestart: 'onRotateStart', rotate: 'onRotate', rotateend: 'onRotateEnd', pitchstart: 'onPitchStart', pitch: 'onPitch', pitchend: 'onPitchEnd' }; const otherEvents = { wheel: 'onWheel', boxzoomstart: 'onBoxZoomStart', boxzoomend: 'onBoxZoomEnd', boxzoomcancel: 'onBoxZoomCancel', resize: 'onResize', load: 'onLoad', render: 'onRender', idle: 'onIdle', remove: 'onRemove', data: 'onData', styledata: 'onStyleData', sourcedata: 'onSourceData', error: 'onError' }; const settingNames = [ 'minZoom', 'maxZoom', 'minPitch', 'maxPitch', 'maxBounds', 'projection', 'renderWorldCopies' ]; const handlerNames = [ 'scrollZoom', 'boxZoom', 'dragRotate', 'dragPan', 'keyboard', 'doubleClickZoom', 'touchZoomRotate', 'touchPitch' ]; /** * A wrapper for mapbox-gl's Map class */ export default class Maplibre { private _MapClass: {new (options: any): MapInstance}; // mapboxgl.Map instance private _map: MapInstance = null; // User-supplied props props: MaplibreProps; // Internal states private _internalUpdate: boolean = false; private _hoveredFeatures: MapGeoJSONFeature[] = null; private _propsedCameraUpdate: ViewState | null = null; private _styleComponents: { light?: LightSpecification; sky?: SkySpecification; projection?: ProjectionSpecification; terrain?: TerrainSpecification | null; } = {}; static savedMaps: Maplibre[] = []; constructor( MapClass: {new (options: any): MapInstance}, props: MaplibreProps, container: HTMLDivElement ) { this._MapClass = MapClass; this.props = props; this._initialize(container); } get map(): MapInstance { return this._map; } setProps(props: MaplibreProps) { const oldProps = this.props; this.props = props; const settingsChanged = this._updateSettings(props, oldProps); const sizeChanged = this._updateSize(props); const viewStateChanged = this._updateViewState(props); this._updateStyle(props, oldProps); this._updateStyleComponents(props); this._updateHandlers(props, oldProps); // If 1) view state has changed to match props and // 2) the props change is not triggered by map events, // it's driven by an external state change. Redraw immediately if (settingsChanged || sizeChanged || (viewStateChanged && !this._map.isMoving())) { this.redraw(); } } static reuse(props: MaplibreProps, container: HTMLDivElement): Maplibre { const that = Maplibre.savedMaps.pop(); if (!that) { return null; } const map = that.map; // When reusing the saved map, we need to reparent the map(canvas) and other child nodes // intoto the new container from the props. // Step 1: reparenting child nodes from old container to new container const oldContainer = map.getContainer(); container.className = oldContainer.className; while (oldContainer.childNodes.length > 0) { container.appendChild(oldContainer.childNodes[0]); } // Step 2: replace the internal container with new container from the react component // @ts-ignore map._container = container; // With maplibre-gl as mapLib, map uses ResizeObserver to observe when its container resizes. // When reusing the saved map, we need to disconnect the observer and observe the new container. // Step 3: telling the ResizeObserver to disconnect and observe the new container // @ts-ignore const resizeObserver = map._resizeObserver; if (resizeObserver) { resizeObserver.disconnect(); resizeObserver.observe(container); } // Step 4: apply new props that.setProps({...props, styleDiffing: false}); map.resize(); const {initialViewState} = props; if (initialViewState) { if (initialViewState.bounds) { map.fitBounds(initialViewState.bounds, {...initialViewState.fitBoundsOptions, duration: 0}); } else { that._updateViewState(initialViewState); } } // Simulate load event if (map.isStyleLoaded()) { map.fire('load'); } else { map.once('style.load', () => map.fire('load')); } // Force reload // @ts-ignore map._update(); return that; } /* eslint-disable complexity,max-statements */ private _initialize(container: HTMLDivElement) { const {props} = this; const {mapStyle = DEFAULT_STYLE} = props; const mapOptions = { ...props, ...props.initialViewState, container, style: normalizeStyle(mapStyle) }; const viewState = mapOptions.initialViewState || mapOptions.viewState || mapOptions; Object.assign(mapOptions, { center: [viewState.longitude || 0, viewState.latitude || 0], zoom: viewState.zoom || 0, pitch: viewState.pitch || 0, bearing: viewState.bearing || 0 }); if (props.gl) { // eslint-disable-next-line const getContext = HTMLCanvasElement.prototype.getContext; // Hijack canvas.getContext to return our own WebGLContext // This will be called inside the mapboxgl.Map constructor // @ts-expect-error HTMLCanvasElement.prototype.getContext = () => { // Unhijack immediately HTMLCanvasElement.prototype.getContext = getContext; return props.gl; }; } const map = new this._MapClass(mapOptions); // Props that are not part of constructor options if (viewState.padding) { map.setPadding(viewState.padding); } if (props.cursor) { map.getCanvas().style.cursor = props.cursor; } // add listeners map.transformCameraUpdate = this._onCameraUpdate; map.on('style.load', () => { // Map style has changed, this would have wiped out all settings from props this._styleComponents = { light: map.getLight(), sky: map.getSky(), // @ts-ignore getProjection() does not exist in v4 projection: map.getProjection?.(), terrain: map.getTerrain() }; this._updateStyleComponents(this.props); }); map.on('sourcedata', () => { // Some sources have loaded, we may need them to attach terrain this._updateStyleComponents(this.props); }); for (const eventName in pointerEvents) { map.on(eventName, this._onPointerEvent); } for (const eventName in cameraEvents) { map.on(eventName, this._onCameraEvent); } for (const eventName in otherEvents) { map.on(eventName, this._onEvent); } this._map = map; } /* eslint-enable complexity,max-statements */ recycle() { // Clean up unnecessary elements before storing for reuse. const container = this.map.getContainer(); const children = container.querySelector('[mapboxgl-children]'); children?.remove(); Maplibre.savedMaps.push(this); } destroy() { this._map.remove(); } // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next // render cycle, which is managed by Mapbox's animation loop. // This removes the synchronization issue caused by requestAnimationFrame. redraw() { const map = this._map as any; // map._render will throw error if style does not exist // https://github.com/mapbox/mapbox-gl-js/blob/fb9fc316da14e99ff4368f3e4faa3888fb43c513 // /src/ui/map.js#L1834 if (map.style) { // cancel the scheduled update if (map._frame) { map._frame.cancel(); map._frame = null; } // the order is important - render() may schedule another update map._render(); } } /* Trigger map resize if size is controlled @param {object} nextProps @returns {bool} true if size has changed */ private _updateSize(nextProps: MaplibreProps): boolean { // Check if size is controlled const {viewState} = nextProps; if (viewState) { const map = this._map; if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) { map.resize(); return true; } } return false; } // Adapted from map.jumpTo /* Update camera to match props @param {object} nextProps @param {bool} triggerEvents - should fire camera events @returns {bool} true if anything is changed */ private _updateViewState(nextProps: MaplibreProps): boolean { const map = this._map; const tr = map.transform; const isMoving = map.isMoving(); // Avoid manipulating the real transform when interaction/animation is ongoing // as it would interfere with Mapbox's handlers if (!isMoving) { const changes = applyViewStateToTransform(tr, nextProps); if (Object.keys(changes).length > 0) { this._internalUpdate = true; map.jumpTo(changes); this._internalUpdate = false; return true; } } return false; } /* Update camera constraints and projection settings to match props @param {object} nextProps @param {object} currProps @returns {bool} true if anything is changed */ private _updateSettings(nextProps: MaplibreProps, currProps: MaplibreProps): boolean { const map = this._map; let changed = false; for (const propName of settingNames) { const propPresent = propName in nextProps || propName in currProps; if (propPresent && !deepEqual(nextProps[propName], currProps[propName])) { changed = true; const nextValue = propName in nextProps ? nextProps[propName] : DEFAULT_SETTINGS[propName]; const setter = map[`set${propName[0].toUpperCase()}${propName.slice(1)}`]; setter?.call(map, nextValue); } } return changed; } /* Update map style to match props */ private _updateStyle(nextProps: MaplibreProps, currProps: MaplibreProps): void { if (nextProps.cursor !== currProps.cursor) { this._map.getCanvas().style.cursor = nextProps.cursor || ''; } if (nextProps.mapStyle !== currProps.mapStyle) { const {mapStyle = DEFAULT_STYLE, styleDiffing = true} = nextProps; const options: any = { diff: styleDiffing }; if ('localIdeographFontFamily' in nextProps) { // @ts-ignore Mapbox specific prop options.localIdeographFontFamily = nextProps.localIdeographFontFamily; } this._map.setStyle(normalizeStyle(mapStyle), options); } } /* Update fog, light, projection and terrain to match props * These props are special because * 1. They can not be applied right away. Certain conditions (style loaded, source loaded, etc.) must be met * 2. They can be overwritten by mapStyle */ private _updateStyleComponents({light, projection, sky, terrain}: MaplibreProps): void { const map = this._map; const currProps = this._styleComponents; // We can safely manipulate map style once it's loaded if (map.style._loaded) { if (light && !deepEqual(light, currProps.light)) { currProps.light = light; map.setLight(light); } if ( projection && !deepEqual(projection, currProps.projection) && projection !== currProps.projection?.type ) { currProps.projection = typeof projection === 'string' ? {type: projection} : projection; // @ts-ignore setProjection does not exist in v4 map.setProjection?.(currProps.projection); } if (sky && !deepEqual(sky, currProps.sky)) { currProps.sky = sky; map.setSky(sky); } if (terrain !== undefined && !deepEqual(terrain, currProps.terrain)) { if (!terrain || map.getSource(terrain.source)) { currProps.terrain = terrain; map.setTerrain(terrain); } } } } /* Update interaction handlers to match props */ private _updateHandlers(nextProps: MaplibreProps, currProps: MaplibreProps): void { const map = this._map; for (const propName of handlerNames) { const newValue = nextProps[propName] ?? true; const oldValue = currProps[propName] ?? true; if (!deepEqual(newValue, oldValue)) { if (newValue) { map[propName].enable(newValue); } else { map[propName].disable(); } } } } private _onEvent = (e: MapEvent) => { // @ts-ignore const cb = this.props[otherEvents[e.type]]; if (cb) { cb(e); } else if (e.type === 'error') { console.error((e as ErrorEvent).error); // eslint-disable-line } }; private _onCameraEvent = (e: ViewStateChangeEvent) => { if (this._internalUpdate) { return; } e.viewState = this._propsedCameraUpdate || transformToViewState(this._map.transform); // @ts-ignore const cb = this.props[cameraEvents[e.type]]; if (cb) { cb(e); } }; private _onCameraUpdate = (tr: TransformLike) => { if (this._internalUpdate) { return tr; } this._propsedCameraUpdate = transformToViewState(tr); return applyViewStateToTransform(tr, this.props); }; private _queryRenderedFeatures(point: Point) { const map = this._map; const {interactiveLayerIds = []} = this.props; try { return map.queryRenderedFeatures(point, { layers: interactiveLayerIds.filter(map.getLayer.bind(map)) }); } catch { // May fail if style is not loaded return []; } } private _updateHover(e: MapMouseEvent) { const {props} = this; const shouldTrackHoveredFeatures = props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave); if (shouldTrackHoveredFeatures) { const eventType = e.type; const wasHovering = this._hoveredFeatures?.length > 0; const features = this._queryRenderedFeatures(e.point); const isHovering = features.length > 0; if (!isHovering && wasHovering) { e.type = 'mouseleave'; this._onPointerEvent(e); } this._hoveredFeatures = features; if (isHovering && !wasHovering) { e.type = 'mouseenter'; this._onPointerEvent(e); } e.type = eventType; } else { this._hoveredFeatures = null; } } private _onPointerEvent = (e: MapMouseEvent) => { if (e.type === 'mousemove' || e.type === 'mouseout') { this._updateHover(e); } // @ts-ignore const cb = this.props[pointerEvents[e.type]]; if (cb) { if (this.props.interactiveLayerIds && e.type !== 'mouseover' && e.type !== 'mouseout') { e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point); } cb(e); delete e.features; } }; } ================================================ FILE: modules/react-maplibre/src/types/common.ts ================================================ import type {PaddingOptions} from 'maplibre-gl'; export type { Point, PointLike, LngLat, LngLatLike, LngLatBounds, LngLatBoundsLike, PaddingOptions, MapGeoJSONFeature } from 'maplibre-gl'; /* Public */ /** Describes the camera's state */ export type ViewState = { /** Longitude at map center */ longitude: number; /** Latitude at map center */ latitude: number; /** Map zoom level */ zoom: number; /** Map rotation bearing in degrees counter-clockwise from north */ bearing: number; /** Map angle in degrees at which the camera is looking at the ground */ pitch: number; /** Dimensions in pixels applied on each side of the viewport for shifting the vanishing point. */ padding: PaddingOptions; }; export interface ImmutableLike { toJS: () => T; } ================================================ FILE: modules/react-maplibre/src/types/events.ts ================================================ import type {Point, LngLat, MapGeoJSONFeature, ViewState} from './common'; import type { Map, Marker, Popup, GeolocateControl, MapLibreEvent, MapMouseEvent as _MapMouseEvent, MapLayerMouseEvent, MapTouchEvent, MapLayerTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent, MapLibreZoomEvent as MapBoxZoomEvent } from 'maplibre-gl'; export type { MapLibreEvent as MapEvent, MapLayerMouseEvent, MapTouchEvent, MapLayerTouchEvent, MapStyleDataEvent, MapSourceDataEvent, MapWheelEvent, MapBoxZoomEvent }; export type MapCallbacks = { onMouseDown?: (e: MapLayerMouseEvent) => void; onMouseUp?: (e: MapLayerMouseEvent) => void; onMouseOver?: (e: MapLayerMouseEvent) => void; onMouseMove?: (e: MapLayerMouseEvent) => void; onClick?: (e: MapLayerMouseEvent) => void; onDblClick?: (e: MapLayerMouseEvent) => void; onMouseEnter?: (e: MapLayerMouseEvent) => void; onMouseLeave?: (e: MapLayerMouseEvent) => void; onMouseOut?: (e: MapLayerMouseEvent) => void; onContextMenu?: (e: MapLayerMouseEvent) => void; onTouchStart?: (e: MapLayerTouchEvent) => void; onTouchEnd?: (e: MapLayerTouchEvent) => void; onTouchMove?: (e: MapLayerTouchEvent) => void; onTouchCancel?: (e: MapLayerTouchEvent) => void; onMoveStart?: (e: ViewStateChangeEvent) => void; onMove?: (e: ViewStateChangeEvent) => void; onMoveEnd?: (e: ViewStateChangeEvent) => void; onDragStart?: (e: ViewStateChangeEvent) => void; onDrag?: (e: ViewStateChangeEvent) => void; onDragEnd?: (e: ViewStateChangeEvent) => void; onZoomStart?: (e: ViewStateChangeEvent) => void; onZoom?: (e: ViewStateChangeEvent) => void; onZoomEnd?: (e: ViewStateChangeEvent) => void; onRotateStart?: (e: ViewStateChangeEvent) => void; onRotate?: (e: ViewStateChangeEvent) => void; onRotateEnd?: (e: ViewStateChangeEvent) => void; onPitchStart?: (e: ViewStateChangeEvent) => void; onPitch?: (e: ViewStateChangeEvent) => void; onPitchEnd?: (e: ViewStateChangeEvent) => void; onWheel?: (e: MapWheelEvent) => void; onBoxZoomStart?: (e: MapBoxZoomEvent) => void; onBoxZoomEnd?: (e: MapBoxZoomEvent) => void; onBoxZoomCancel?: (e: MapBoxZoomEvent) => void; onResize?: (e: MapLibreEvent) => void; onLoad?: (e: MapLibreEvent) => void; onRender?: (e: MapLibreEvent) => void; onIdle?: (e: MapLibreEvent) => void; onError?: (e: ErrorEvent) => void; onRemove?: (e: MapLibreEvent) => void; onData?: (e: MapStyleDataEvent | MapSourceDataEvent) => void; onStyleData?: (e: MapStyleDataEvent) => void; onSourceData?: (e: MapSourceDataEvent) => void; }; interface MapEvent { type: string; target: SourceT; originalEvent: OriginalEventT; } export type ErrorEvent = MapEvent & { type: 'error'; error: Error; }; export type MapMouseEvent = _MapMouseEvent & { point: Point; lngLat: LngLat; features?: MapGeoJSONFeature[]; }; export type ViewStateChangeEvent = | (MapEvent & { type: 'movestart' | 'move' | 'moveend' | 'zoomstart' | 'zoom' | 'zoomend'; viewState: ViewState; }) | (MapEvent & { type: | 'rotatestart' | 'rotate' | 'rotateend' | 'dragstart' | 'drag' | 'dragend' | 'pitchstart' | 'pitch' | 'pitchend'; viewState: ViewState; }); export type PopupEvent = { type: 'open' | 'close'; target: Popup; }; export type MarkerEvent = MapEvent; export type MarkerDragEvent = MarkerEvent & { type: 'dragstart' | 'drag' | 'dragend'; lngLat: LngLat; }; export type GeolocateEvent = MapEvent; export type GeolocateResultEvent = GeolocateEvent & GeolocationPosition; export type GeolocateErrorEvent = GeolocateEvent & GeolocationPositionError; ================================================ FILE: modules/react-maplibre/src/types/internal.ts ================================================ // Internal types import type {LngLat, PaddingOptions} from 'maplibre-gl'; /** * maplibre's Transform interface / CameraUpdateTransformFunction argument */ export type TransformLike = { center: LngLat; zoom: number; roll?: number; pitch: number; bearing: number; elevation: number; padding?: PaddingOptions; }; export type { GeoJSONSource as GeoJSONSourceImplementation, ImageSource as ImageSourceImplementation, CanvasSource as CanvasSourceImplementation, VectorTileSource as VectorSourceImplementation, RasterTileSource as RasterSourceImplementation, RasterDEMTileSource as RasterDemSourceImplementation, VideoSource as VideoSourceImplementation, Source as AnySourceImplementation } from 'maplibre-gl'; ================================================ FILE: modules/react-maplibre/src/types/lib.ts ================================================ import type { Map, MapOptions, Marker, MarkerOptions, Popup, PopupOptions, AttributionControl, AttributionControlOptions, FullscreenControl, FullscreenControlOptions, GeolocateControl, GeolocateControlOptions, NavigationControl, NavigationControlOptions, ScaleControl, ScaleControlOptions, TerrainControl, TerrainSpecification, LogoControl, LogoControlOptions, GlobeControl } from 'maplibre-gl'; export type { ControlPosition, IControl, Map as MapInstance, MapOptions, Marker as MarkerInstance, MarkerOptions, Popup as PopupInstance, PopupOptions, AttributionControl as AttributionControlInstance, AttributionControlOptions, FullscreenControl as FullscreenControlInstance, FullscreenControlOptions, GeolocateControl as GeolocateControlInstance, GeolocateControlOptions, NavigationControl as NavigationControlInstance, NavigationControlOptions, ScaleControl as ScaleControlInstance, ScaleControlOptions, TerrainControl as TerrainControlInstance, LogoControl as LogoControlInstance, LogoControlOptions, GlobeControl as GlobeControlInstance, CustomLayerInterface } from 'maplibre-gl'; /** * A user-facing type that represents the minimal intersection between Mapbox and Maplibre * User provided `mapLib` is supposed to implement this interface * Only losely typed for compatibility */ export interface MapLib { supported?: (options: any) => boolean; Map: {new (options: MapOptions): Map}; Marker: {new (options: MarkerOptions): Marker}; Popup: {new (options: PopupOptions): Popup}; AttributionControl: {new (options: AttributionControlOptions): AttributionControl}; FullscreenControl: {new (options: FullscreenControlOptions): FullscreenControl}; GeolocateControl: {new (options: GeolocateControlOptions): GeolocateControl}; NavigationControl: {new (options: NavigationControlOptions): NavigationControl}; ScaleControl: {new (options: ScaleControlOptions): ScaleControl}; TerrainControl: {new (options: TerrainSpecification): TerrainControl}; LogoControl: {new (options: LogoControlOptions): LogoControl}; GlobeControl: {new (options: any): GlobeControl}; } ================================================ FILE: modules/react-maplibre/src/types/style-spec.ts ================================================ /* * Maplibre Style Specification types * Type names are aligned with mapbox */ export type { // Layers LayerSpecification, FillLayerSpecification, LineLayerSpecification, SymbolLayerSpecification, CircleLayerSpecification, HeatmapLayerSpecification, FillExtrusionLayerSpecification, RasterLayerSpecification, HillshadeLayerSpecification, BackgroundLayerSpecification, // Sources SourceSpecification, VectorSourceSpecification, RasterSourceSpecification, RasterDEMSourceSpecification, GeoJSONSourceSpecification, VideoSourceSpecification, ImageSourceSpecification, CanvasSourceSpecification, // Style StyleSpecification, SkySpecification, LightSpecification, TerrainSpecification, ProjectionSpecification } from 'maplibre-gl'; ================================================ FILE: modules/react-maplibre/src/utils/apply-react-style.ts ================================================ import * as React from 'react'; // This is a simplified version of // https://github.com/facebook/react/blob/4131af3e4bf52f3a003537ec95a1655147c81270/src/renderers/dom/shared/CSSPropertyOperations.js#L62 const unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/; export function applyReactStyle(element: HTMLElement, styles: React.CSSProperties) { if (!element || !styles) { return; } const style = element.style; for (const key in styles) { const value = styles[key]; if (Number.isFinite(value) && !unitlessNumber.test(key)) { style[key] = `${value}px`; } else { style[key] = value; } } } ================================================ FILE: modules/react-maplibre/src/utils/assert.ts ================================================ export default function assert(condition: any, message: string) { if (!condition) { throw new Error(message); } } ================================================ FILE: modules/react-maplibre/src/utils/compare-class-names.ts ================================================ /** Compare two classNames string and return the difference */ export function compareClassNames( prevClassName: string | undefined, nextClassName: string | undefined ): string[] | null { if (prevClassName === nextClassName) { return null; } const prevClassList = getClassList(prevClassName); const nextClassList = getClassList(nextClassName); const diff: string[] = []; for (const c of nextClassList) { if (!prevClassList.has(c)) { diff.push(c); } } for (const c of prevClassList) { if (!nextClassList.has(c)) { diff.push(c); } } return diff.length === 0 ? null : diff; } function getClassList(className: string | undefined) { return new Set(className ? className.trim().split(/\s+/) : []); } ================================================ FILE: modules/react-maplibre/src/utils/deep-equal.ts ================================================ import type {PointLike} from '../types/common'; /** * Compare two points * @param a * @param b * @returns true if the points are equal */ export function arePointsEqual(a?: PointLike, b?: PointLike): boolean { const ax = Array.isArray(a) ? a[0] : a ? a.x : 0; const ay = Array.isArray(a) ? a[1] : a ? a.y : 0; const bx = Array.isArray(b) ? b[0] : b ? b.x : 0; const by = Array.isArray(b) ? b[1] : b ? b.y : 0; return ax === bx && ay === by; } /* eslint-disable complexity */ /** * Compare any two objects * @param a * @param b * @returns true if the objects are deep equal */ export function deepEqual(a: any, b: any): boolean { if (a === b) { return true; } if (!a || !b) { return false; } if (Array.isArray(a)) { if (!Array.isArray(b) || a.length !== b.length) { return false; } for (let i = 0; i < a.length; i++) { if (!deepEqual(a[i], b[i])) { return false; } } return true; } else if (Array.isArray(b)) { return false; } if (typeof a === 'object' && typeof b === 'object') { const aKeys = Object.keys(a); const bKeys = Object.keys(b); if (aKeys.length !== bKeys.length) { return false; } for (const key of aKeys) { if (!b.hasOwnProperty(key)) { return false; } if (!deepEqual(a[key], b[key])) { return false; } } return true; } return false; } ================================================ FILE: modules/react-maplibre/src/utils/set-globals.ts ================================================ export type GlobalSettings = { /** The maximum number of images (raster tiles, sprites, icons) to load in parallel. * @default 16 */ maxParallelImageRequests?: number; /** The map's RTL text plugin. Necessary for supporting the Arabic and Hebrew languages, which are written right-to-left. */ RTLTextPlugin?: string | {pluginUrl: string; lazy?: boolean}; /** The number of web workers instantiated on a page with maplibre-gl maps. * @default 2 */ workerCount?: number; /** Provides an interface for loading maplibre-gl's WebWorker bundle from a self-hosted URL. * This is useful if your site needs to operate in a strict CSP (Content Security Policy) environment * wherein you are not allowed to load JavaScript code from a Blob URL, which is default behavior. */ workerUrl?: string; }; export default function setGlobals(mapLib: any, props: GlobalSettings) { const {RTLTextPlugin, maxParallelImageRequests, workerCount, workerUrl} = props; if ( RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === 'unavailable' ) { const {pluginUrl, lazy = true} = typeof RTLTextPlugin === 'string' ? {pluginUrl: RTLTextPlugin} : RTLTextPlugin; mapLib.setRTLTextPlugin( pluginUrl, (error?: Error) => { if (error) { // eslint-disable-next-line console.error(error); } }, lazy ); } if (maxParallelImageRequests !== undefined) { mapLib.setMaxParallelImageRequests(maxParallelImageRequests); } if (workerCount !== undefined) { mapLib.setWorkerCount(workerCount); } if (workerUrl !== undefined) { mapLib.setWorkerUrl(workerUrl); } } ================================================ FILE: modules/react-maplibre/src/utils/style-utils.ts ================================================ import type {StyleSpecification} from '../types/style-spec'; import type {ImmutableLike} from '../types/common'; const refProps = ['type', 'source', 'source-layer', 'minzoom', 'maxzoom', 'filter', 'layout']; // Prepare a map style object for diffing // If immutable - convert to plain object // Work around some issues in older styles that would fail Mapbox's diffing export function normalizeStyle( style: string | StyleSpecification | ImmutableLike ): string | StyleSpecification { if (!style) { return null; } if (typeof style === 'string') { return style; } if ('toJS' in style) { style = style.toJS(); } if (!style.layers) { return style; } const layerIndex = {}; for (const layer of style.layers) { layerIndex[layer.id] = layer; } const layers = style.layers.map(layer => { let normalizedLayer: typeof layer = null; if ('interactive' in layer) { normalizedLayer = Object.assign({}, layer); // Breaks style diffing :( // @ts-ignore legacy field not typed delete normalizedLayer.interactive; } // Style diffing doesn't work with refs so expand them out manually before diffing. // @ts-ignore legacy field not typed const layerRef = layerIndex[layer.ref]; if (layerRef) { normalizedLayer = normalizedLayer || Object.assign({}, layer); // @ts-ignore delete normalizedLayer.ref; // https://github.com/mapbox/mapbox-gl-js/blob/master/src/style-spec/deref.js for (const propName of refProps) { if (propName in layerRef) { normalizedLayer[propName] = layerRef[propName]; } } } return normalizedLayer || layer; }); // Do not mutate the style object provided by the user return {...style, layers}; } ================================================ FILE: modules/react-maplibre/src/utils/transform.ts ================================================ import type {MaplibreProps} from '../maplibre/maplibre'; import type {ViewState} from '../types/common'; import type {TransformLike} from '../types/internal'; import {deepEqual} from './deep-equal'; /** * Capture a transform's current state * @param transform * @returns descriptor of the view state */ export function transformToViewState(tr: TransformLike): ViewState { return { longitude: tr.center.lng, latitude: tr.center.lat, zoom: tr.zoom, pitch: tr.pitch, bearing: tr.bearing, padding: tr.padding }; } /* eslint-disable complexity */ /** * Applies requested view state to a transform * @returns an object containing detected changes */ export function applyViewStateToTransform( /** An object that describes Maplibre's camera state */ tr: TransformLike, /** Props from Map component */ props: MaplibreProps ): Partial { const v: Partial = props.viewState || props; const changes: Partial = {}; if ( 'longitude' in v && 'latitude' in v && (v.longitude !== tr.center.lng || v.latitude !== tr.center.lat) ) { const LngLat = tr.center.constructor; // @ts-expect-error we should not import LngLat class from maplibre-gl because we don't know the source of mapLib changes.center = new LngLat(v.longitude, v.latitude); } if ('zoom' in v && v.zoom !== tr.zoom) { changes.zoom = v.zoom; } if ('bearing' in v && v.bearing !== tr.bearing) { changes.bearing = v.bearing; } if ('pitch' in v && v.pitch !== tr.pitch) { changes.pitch = v.pitch; } if (v.padding && tr.padding && !deepEqual(v.padding, tr.padding)) { changes.padding = v.padding; } return changes; } ================================================ FILE: modules/react-maplibre/src/utils/use-isomorphic-layout-effect.ts ================================================ // From https://github.com/streamich/react-use/blob/master/src/useIsomorphicLayoutEffect.ts // useLayoutEffect but does not trigger warning in server-side rendering import {useEffect, useLayoutEffect} from 'react'; const useIsomorphicLayoutEffect = typeof document !== 'undefined' ? useLayoutEffect : useEffect; export default useIsomorphicLayoutEffect; ================================================ FILE: modules/react-maplibre/test/.eslintrc ================================================ { "rules": { "import/no-unresolved": 0, "import/no-extraneous-dependencies": 0 } } ================================================ FILE: modules/react-maplibre/test/components/controls.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import { Map, AttributionControl, FullscreenControl, GeolocateControl, NavigationControl, ScaleControl } from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Controls', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-ctrl-attrib'), 'Rendered '); root.render( ); await sleep(1); t.ok( rootContainer.querySelector('.maplibregl-ctrl-fullscreen'), 'Rendered ' ); const geolocateControlRef = {current: null}; root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-ctrl-geolocate'), 'Rendered '); t.ok(geolocateControlRef.current, 'GeolocateControl created'); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-ctrl-zoom-in'), 'Rendered '); root.render( ); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-ctrl-scale'), 'Rendered '); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/components/index.js ================================================ import './map.spec'; import './controls.spec'; import './source.spec'; import './layer.spec'; import './marker.spec'; import './popup.spec'; import './use-map.spec'; ================================================ FILE: modules/react-maplibre/test/components/layer.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source, Layer} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const pointLayer = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#007cbf' } }; const pointLayer2 = { type: 'circle', paint: { 'circle-radius': 10, 'circle-color': '#000000' }, layout: { visibility: 'none' } }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); const layer = mapRef.current.getLayer('my-layer'); t.ok(layer, 'Layer is added'); root.render( ); await sleep(1); t.is(layer.visibility, 'none', 'Layer is updated'); root.render( ); await sleep(50); t.ok(mapRef.current.getLayer('my-layer'), 'Layer is added after style change'); root.render(); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); t.notOk(mapRef.current.getLayer('my-layer'), 'Layer is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/components/map.spec.jsx ================================================ /* global setTimeout, document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Map', async t => { t.ok(Map, 'Map is defined'); const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let onloadCalled = 0; const onLoad = () => onloadCalled++; root.render( ); await waitForMapLoad(mapRef); t.ok(mapRef.current, 'Map is created'); t.is(mapRef.current.getCenter().lng, -100, 'longitude is set'); t.is(mapRef.current.getCenter().lat, 40, 'latitude is set'); t.is(mapRef.current.getZoom(), 4, 'zoom is set'); root.render(); await sleep(1); t.is(mapRef.current.getCenter().lng, -122, 'longitude is updated'); t.is(mapRef.current.getCenter().lat, 38, 'latitude is updated'); t.is(mapRef.current.getZoom(), 14, 'zoom is updated'); t.is(onloadCalled, 1, 'onLoad is called'); root.unmount(); t.end(); }); test('Map#uncontrolled', t => { const root = createRoot(document.createElement('div')); function onLoad(e) { e.target.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } let lastCenter; function onRender(e) { const center = e.target.getCenter(); if (lastCenter) { t.ok(lastCenter.lng > center.lng && lastCenter.lat > center.lat, `animated to ${center}`); } lastCenter = center; } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#controlled#no-update', t => { const root = createRoot(document.createElement('div')); function onLoad(e) { e.target.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(e) { const center = e.target.getCenter(); t.ok(center.lng === -100 && center.lat === 40, `map center should match props: ${center}`); } function onMoveEnd() { root.unmount(); t.end(); } root.render( ); }); test('Map#controlled#mirror-back', t => { const root = createRoot(document.createElement('div')); function onLoad(e) { e.target.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs, e) { const center = e.target.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setViewState(e.viewState)} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); test('Map#controlled#delayed-update', t => { const root = createRoot(document.createElement('div')); function onLoad(e) { e.target.easeTo({center: [-122, 38], zoom: 14, duration: 100}); } function onRender(vs, e) { const center = e.target.getCenter(); t.ok( vs.longitude === center.lng && vs.latitude === center.lat, `map center should match state: ${center}` ); } function onMoveEnd() { root.unmount(); t.end(); } function App() { const [viewState, setViewState] = React.useState({ longitude: -100, latitude: 40, zoom: 4 }); return ( setTimeout(() => setViewState(e.viewState))} onRender={onRender.bind(null, viewState)} onMoveEnd={onMoveEnd} /> ); } root.render(); }); ================================================ FILE: modules/react-maplibre/test/components/marker.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Marker} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Marker', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const markerRef = {current: null}; const mapRef = {current: null}; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-marker'), 'Marker is attached to DOM'); t.ok(markerRef.current, 'Marker is created'); const marker = markerRef.current; const offset = marker.getOffset(); const draggable = marker.isDraggable(); const rotation = marker.getRotation(); const pitchAlignment = marker.getPitchAlignment(); const rotationAlignment = marker.getRotationAlignment(); root.render( ); t.is(offset, marker.getOffset(), 'offset did not change deeply'); let callbackType = ''; root.render( (callbackType = 'dragstart')} onDrag={() => (callbackType = 'drag')} onDragEnd={() => (callbackType = 'dragend')} /> ); await sleep(1); t.not(offset, marker.getOffset(), 'offset is updated'); t.not(draggable, marker.isDraggable(), 'draggable is updated'); t.not(rotation, marker.getRotation(), 'rotation is updated'); t.not(pitchAlignment, marker.getPitchAlignment(), 'pitchAlignment is updated'); t.not(rotationAlignment, marker.getRotationAlignment(), 'rotationAlignment is updated'); t.ok(marker._element.classList.contains('classA'), 'className is updated'); marker.fire('dragstart'); t.is(callbackType, 'dragstart', 'onDragStart called'); marker.fire('drag'); t.is(callbackType, 'drag', 'onDrag called'); marker.fire('dragend'); t.is(callbackType, 'dragend', 'onDragEnd called'); root.render(); await sleep(1); t.notOk(markerRef.current, 'marker is removed'); root.render(
); await sleep(1); t.ok(rootContainer.querySelector('#marker-content'), 'content is rendered'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/components/popup.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Popup} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Popup', async t => { const rootContainer = document.createElement('div'); const root = createRoot(rootContainer); const mapRef = {current: null}; const popupRef = {current: null}; root.render( You are here ); await waitForMapLoad(mapRef); await sleep(1); t.ok(rootContainer.querySelector('.maplibregl-popup'), 'Popup is attached to DOM'); t.ok(popupRef.current, 'Popup is created'); const popup = popupRef.current; const {anchor, offset, maxWidth} = popup.options; root.render( ); await sleep(1); t.is(offset, popup.options.offset, 'offset did not change deeply'); t.ok(rootContainer.querySelector('#popup-content'), 'content is rendered'); root.render( ); await sleep(1); t.not(offset, popup.options.offset, 'offset is updated'); t.not(anchor, popup.options.anchor, 'anchor is updated'); t.not(maxWidth, popup.options.maxWidth, 'maxWidth is updated'); root.render( ); await sleep(1); t.ok(popup._container.classList.contains('classA'), 'className is updated'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/components/source.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, Source} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('Source/Layer', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; const mapStyle = {version: 8, sources: {}, layers: []}; const geoJSON = { type: 'Point', coordinates: [0, 0] }; const geoJSON2 = { type: 'Point', coordinates: [1, 1] }; root.render( ); await waitForMapLoad(mapRef); await sleep(1); t.ok(mapRef.current.getSource('my-data'), 'Source is added'); root.render( ); await sleep(50); t.ok(mapRef.current.getSource('my-data'), 'Source is added after style change'); root.render( ); await sleep(1); const sourceData = await mapRef.current.getSource('my-data')?.getData(); t.deepEqual(sourceData, geoJSON2, 'Source is updated'); root.render(); await sleep(1); t.notOk(mapRef.current.getSource('my-data'), 'Source is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/components/use-map.spec.jsx ================================================ /* global document */ import test from 'tape-promise/tape'; import * as React from 'react'; import {createRoot} from 'react-dom/client'; import {Map, MapProvider, useMap} from '@vis.gl/react-maplibre'; import {sleep, waitForMapLoad} from '../utils/test-utils'; test('useMap', async t => { const root = createRoot(document.createElement('div')); const mapRef = {current: null}; let maps = null; function TestControl() { maps = useMap(); return null; } root.render( ); await waitForMapLoad(mapRef); t.ok(maps.mapA, 'Context has mapA'); t.ok(maps.mapB, 'Context has mapB'); root.render( ); await sleep(50); t.ok(maps.mapA, 'Context has mapA'); t.notOk(maps.mapB, 'mapB is removed'); root.render( ); await sleep(50); t.notOk(maps.mapA, 'mapA is removed'); root.unmount(); t.end(); }); ================================================ FILE: modules/react-maplibre/test/utils/apply-react-style.spec.js ================================================ import test from 'tape-promise/tape'; import {applyReactStyle} from '@vis.gl/react-maplibre/utils/apply-react-style'; test('applyReactStyle', t => { /* global document */ if (typeof document === 'undefined') { t.end(); return; } const div = document.createElement('div'); t.doesNotThrow(() => applyReactStyle(null, {}), 'null element'); t.doesNotThrow(() => applyReactStyle(div, null), 'null style'); applyReactStyle(div, {marginLeft: 4, height: 24, lineHeight: 2, zIndex: 1, flexGrow: 0.5}); t.is(div.style.marginLeft, '4px', 'appended px to numeric value'); t.is(div.style.height, '24px', 'appended px to numeric value'); t.is(div.style.lineHeight, '2', 'unitless numeric property'); t.is(div.style.zIndex, '1', 'unitless numeric property'); t.is(div.style.flexGrow, '0.5', 'unitless numeric property'); t.end(); }); ================================================ FILE: modules/react-maplibre/test/utils/compare-class-names.spec.js ================================================ import test from 'tape-promise/tape'; import {compareClassNames} from '@vis.gl/react-maplibre/utils/compare-class-names'; test('compareClassNames', t => { const TEST_CASES = [ { title: 'Empty class names', prevClassName: '', nextClassName: '', output: null }, { title: 'Identical class names', prevClassName: 'marker active', nextClassName: 'active marker ', output: null }, { title: 'Addition', prevClassName: undefined, nextClassName: 'marker', output: ['marker'] }, { title: 'Addition', prevClassName: 'marker', nextClassName: 'marker active', output: ['active'] }, { title: 'Removal', prevClassName: 'marker active', nextClassName: 'marker', output: ['active'] }, { title: 'Multiple addition & removal', prevClassName: 'marker active', nextClassName: 'marker hovered hidden', output: ['hovered', 'hidden', 'active'] } ]; for (const testCase of TEST_CASES) { t.deepEqual( compareClassNames(testCase.prevClassName, testCase.nextClassName), testCase.output, testCase.title ); } t.end(); }); ================================================ FILE: modules/react-maplibre/test/utils/deep-equal.spec.js ================================================ import test from 'tape-promise/tape'; import {deepEqual, arePointsEqual} from '@vis.gl/react-maplibre/utils/deep-equal'; test('deepEqual', t => { const testCases = [ { a: null, b: null, result: true }, { a: undefined, b: 0, result: false }, { a: [1, 2, 3], b: [1, 2, 3], result: true }, { a: [1, 2], b: [1, 2, 3], result: false }, { a: [1, 2], b: {0: 1, 1: 2}, result: false }, { a: {x: 0, y: 0, offset: [1, -1]}, b: {x: 0, y: 0, offset: [1, -1]}, result: true }, { a: {x: 0, y: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false }, { a: {x: 0, y: 0, z: 0}, b: {x: 0, y: 0, offset: [1, -1]}, result: false } ]; for (const {a, b, result} of testCases) { t.is(deepEqual(a, b), result, `${JSON.stringify(a)} vs ${JSON.stringify(b)}`); if (a !== b) { t.is(deepEqual(b, a), result, `${JSON.stringify(b)} vs ${JSON.stringify(a)}`); } } t.end(); }); test('arePointsEqual', t => { const testCases = [ { a: undefined, b: undefined, result: true }, { a: undefined, b: [0, 0], result: true }, { a: undefined, b: [0, 1], result: false }, { a: undefined, b: [1, 0], result: false }, { a: {x: 1, y: 1}, b: [1, 1], result: true } ]; for (const {a, b, result} of testCases) { t.is(arePointsEqual(a, b), result, `${JSON.stringify(a)}, ${JSON.stringify(b)}`); if (a !== b) { t.is(arePointsEqual(b, a), result, `${JSON.stringify(b)}, ${JSON.stringify(a)}`); } } t.end(); }); ================================================ FILE: modules/react-maplibre/test/utils/index.js ================================================ import './deep-equal.spec'; import './transform.spec'; import './style-utils.spec'; import './apply-react-style.spec'; import './compare-class-names.spec'; ================================================ FILE: modules/react-maplibre/test/utils/style-utils.spec.js ================================================ import test from 'tape-promise/tape'; import {normalizeStyle} from '@vis.gl/react-maplibre/utils/style-utils'; const testStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 }, interactive: true }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20, interactive: true }, { id: 'park-2', ref: 'park', paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', ref: 'road', minzoom: 10, maxzoom: 12, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; const expectedStyle = { version: 8, name: 'Test', sources: { mapbox: { url: 'mapbox://mapbox.mapbox-streets-v7', type: 'vector' } }, sprite: 'mapbox://sprites/mapbox/basic-v8', glyphs: 'mapbox://fonts/mapbox/{fontstack}/{range}.pbf', layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#dedede' } }, { id: 'park', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#d2edae', 'fill-opacity': 0.75 } }, { id: 'road', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', paint: { 'line-color': '#efefef', 'line-width': { base: 1.55, stops: [ [4, 0.25], [20, 30] ] } }, minzoom: 5, maxzoom: 20 }, { id: 'park-2', type: 'fill', source: 'mapbox', 'source-layer': 'landuse_overlay', filter: ['==', 'class', 'park'], paint: { 'fill-color': '#00f080', 'fill-opacity': 0.5 } }, { id: 'road-outline', source: 'mapbox', 'source-layer': 'road', layout: { 'line-cap': 'butt', 'line-join': 'miter' }, filter: ['all', ['==', '$type', 'LineString']], type: 'line', minzoom: 5, maxzoom: 20, paint: { 'line-color': '#efefef', 'line-width': { base: 2, stops: [ [4, 0.5], [20, 40] ] } } } ] }; test('normalizeStyle', t => { // Make sure the style is not mutated freezeRecursive(testStyle); t.is(normalizeStyle(null), null, 'Handles null'); t.is( normalizeStyle('mapbox://styles/mapbox/light-v9'), 'mapbox://styles/mapbox/light-v9', 'Handles url string' ); let result = normalizeStyle(testStyle); t.notEqual(result, testStyle, 'style is not mutated'); t.deepEqual(result, expectedStyle, 'plain object style is normalized'); // Immutable-like object result = normalizeStyle({toJS: () => testStyle}); t.deepEqual(result, expectedStyle, 'immutable style is normalized'); t.end(); }); function freezeRecursive(obj) { if (!obj) return; if (typeof obj === 'object') { if (Array.isArray(obj)) { for (const el of obj) { freezeRecursive(el); } } else { for (const key in obj) { freezeRecursive(obj[key]); } } Object.freeze(obj); } } ================================================ FILE: modules/react-maplibre/test/utils/test-utils.jsx ================================================ /* global setTimeout */ export function sleep(milliseconds) { return new Promise(resolve => setTimeout(resolve, milliseconds)); } export function waitForMapLoad(mapRef) { return new Promise(resolve => { const check = () => { if (mapRef.current?.isStyleLoaded()) { resolve(); } else { setTimeout(check, 50); } }; check(); }); } ================================================ FILE: modules/react-maplibre/test/utils/transform.spec.js ================================================ import test from 'tape-promise/tape'; import { transformToViewState, applyViewStateToTransform } from '@vis.gl/react-maplibre/utils/transform'; import maplibregl from 'maplibre-gl'; test('transformToViewState', t => { const tr = { center: new maplibregl.LngLat(-122.45, 37.78), zoom: 10.5, bearing: -70, pitch: 30, padding: {top: 0, left: 0, right: 0, bottom: 0} }; t.deepEqual(transformToViewState(tr), { longitude: -122.45, latitude: 37.78, zoom: 10.5, bearing: -70, pitch: 30, padding: {top: 0, left: 0, right: 0, bottom: 0} }); t.end(); }); test('applyViewStateToTransform', t => { const tr = { center: new maplibregl.LngLat(-122.45, 37.78), zoom: 10.5, bearing: -70, pitch: 30, padding: {top: 0, left: 0, right: 0, bottom: 0} }; let changed = applyViewStateToTransform(tr, {}); t.deepEqual(changed, {}, 'no changes detected'); changed = applyViewStateToTransform(tr, {longitude: -10, latitude: 5}); t.deepEqual( changed, { center: new maplibregl.LngLat(-10, 5) }, 'center changed' ); changed = applyViewStateToTransform(tr, {zoom: 11, pitch: 30, bearing: -70}); t.deepEqual(changed, {zoom: 11}, 'zoom changed'); changed = applyViewStateToTransform(tr, {zoom: 10.5, pitch: 40, bearing: -70}); t.deepEqual(changed, {pitch: 40}, 'pitch changed'); changed = applyViewStateToTransform(tr, {zoom: 10.5, pitch: 30, bearing: 270}); t.deepEqual(changed, {bearing: 270}, 'bearing changed'); changed = applyViewStateToTransform(tr, {padding: {left: 10, right: 10, top: 10, bottom: 10}}); t.deepEqual(changed, {padding: {left: 10, right: 10, top: 10, bottom: 10}}, 'bearing changed'); changed = applyViewStateToTransform(tr, {viewState: {pitch: 30}}); t.deepEqual(changed, {}, 'nothing changed'); t.end(); }); ================================================ FILE: modules/react-maplibre/tsconfig.json ================================================ { "extends": "../../tsconfig.json", "include": ["src/**/*"], "exclude": ["node_modules"], "compilerOptions": { "composite": true, "rootDir": "src", "outDir": "dist" }, "references": [ ] } ================================================ FILE: package.json ================================================ { "name": "react-map-gl-monorepo", "description": "React components for MapLibre GL JS and Mapbox GL JS", "private": true, "repository": { "type": "git", "url": "https://github.com/visgl/react-map-gl.git" }, "license": "MIT", "type": "module", "workspaces": [ "modules/*" ], "scripts": { "bootstrap": "yarn && ocular-bootstrap && npm run build", "build": "ocular-clean && ocular-build", "lint": "ocular-lint", "publish-beta": "ocular-publish version-only-beta", "publish-prod": "ocular-publish version-only-prod", "test": "ocular-test", "test-fast": "ocular-build && ocular-test node", "metrics": "ocular-metrics", "update-release-branch": "scripts/update-release-branch.sh" }, "devDependencies": { "@types/node": "^22.0.0", "@types/react": "^16.0.0", "@vis.gl/dev-tools": "1.0.0-alpha.21", "@vis.gl/ts-plugins": "1.0.0-alpha.21", "mapbox-gl-v1": "npm:mapbox-gl@1.13.0", "mapbox-gl-v3": "npm:mapbox-gl@3.9.0", "pre-commit": "^1.2.2", "puppeteer": "^22.4.0", "react": "^18.0.0", "react-dom": "^18.0.0", "typescript": "^5.0.0" }, "pre-commit": [ "test-fast" ], "volta": { "node": "18.20.5", "yarn": "1.22.22" } } ================================================ FILE: scripts/update-release-branch.sh ================================================ #!/bin/bash # Example: # update-release-branch.sh 8.0 set -e BRANCH=`echo "$1-release"` VERSION=`echo "$1.0"` echo "Updating branch to ${BRANCH}..." # Replace source links in docs and examples find docs -mindepth 2 -iname "*.md" -exec perl -i -pe "s/react-map-gl\/(tree|blob)\/(master|[0-9\.]+-release)/react-map-gl\/tree\/${BRANCH}/g" {} \; find examples \( -iname "*.js" -iname "*.jsx" -iname "*.ts" -o -iname "*.tsx" \) -type f -exec perl -i -pe "s/react-map-gl\/(tree|blob)\/(master|[0-9\.]+-release)/react-map-gl\/tree\/${BRANCH}/g" {} \; # Bump dependencies in examples update_dep() { local FILE=$1 local VERSION=$2 cat $FILE | jq ".dependencies |= . + \ with_entries(select(.key | match(\"react-map-gl\")) | .value |= \"^${VERSION}\")" > temp mv temp $FILE } # https://stackoverflow.com/questions/4321456/find-exec-a-shell-function-in-linux export -f update_dep find examples -type f -name "package.json" -exec bash -c 'update_dep "$0" $1' {} $VERSION \; ================================================ FILE: test/.eslintrc ================================================ { "rules": { "import/no-unresolved": 0, "import/no-extraneous-dependencies": 0 } } ================================================ FILE: test/apps/reuse-maps/index.html ================================================ react-map-gl Example
================================================ FILE: test/apps/reuse-maps/package.json ================================================ { "scripts": { "start": "vite --open", "start-local": "vite --config ../../examples/vite.config.local.js" }, "dependencies": { "react": "^17.0.0", "react-dom": "^17.0.0", "react-map-gl": "^7.0.0", "mapbox-gl": "^2.0.0" }, "devDependencies": { "typescript": "^4.0.0", "vite": "^4.0.0" } } ================================================ FILE: test/apps/reuse-maps/src/app.tsx ================================================ import * as React from 'react'; import {useState} from 'react'; import {render} from 'react-dom'; import Map, {MapProps} from 'react-map-gl'; const TOKEN = ''; // Set your mapbox token here const CONFIGS: MapProps[] = [ { style: {width: '100%', height: '100%'}, mapStyle: 'mapbox://styles/mapbox/dark-v9', initialViewState: { longitude: -122.4, latitude: 37.8, zoom: 12 } }, { style: {width: 400, height: 300, margin: 100}, mapStyle: 'mapbox://styles/mapbox/light-v9', initialViewState: { bounds: [ [-125, 35], [-70, 45] ] } }, { style: {width: '50vw', height: '100vh', marginLeft: '50vw'}, mapStyle: 'mapbox://styles/mapbox/streets-v9', longitude: -70.4, latitude: 40.1, zoom: 6 } ]; export default function App() { const [key, setKey] = useState(0); const [showMap, setShowMap] = useState(true); const onClickBtn = () => { if (!showMap) { setKey((key + 1) % CONFIGS.length); } setShowMap(!showMap); }; const onLoad = () => console.log(key, 'loaded'); // eslint-disable-line return ( <> {showMap && } ); } export function renderToDom(container) { render(, container); } ================================================ FILE: test/apps/reuse-maps/tsconfig.json ================================================ { "compilerOptions": { "target": "es2020", "jsx": "react", "allowSyntheticDefaultImports": true, "moduleResolution": "node", "sourceMap": true, "module": "ES2020" } } ================================================ FILE: test/apps/reuse-maps/vite.config.js ================================================ export default { define: { 'process.env.MapboxAccessToken': JSON.stringify(process.env.MapboxAccessToken) } }; ================================================ FILE: test/browser.js ================================================ /* global window */ import test from 'tape'; test.onFinish(window.browserTestDriver_finish); test.onFailure(window.browserTestDriver_fail); import '../modules/main/test/components'; import '../modules/main/test/utils'; import '../modules/react-mapbox/test/components'; import '../modules/react-mapbox/test/utils'; import '../modules/react-maplibre/test/components'; import '../modules/react-maplibre/test/utils'; // import './render'; ================================================ FILE: test/data/sprite/tools/14/sprites.json ================================================ { "ARE_EMIRATE_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "ARE_EMIRATE_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "ARE_EMIRATE_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "ARE_EMIRATE_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "ARE_EMIRATE_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "ARE_EMIRATE_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "ARE_EMIRATE_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "ARE_EMIRATE_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "ARE_EMIRATE_HIGHWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "ARE_EMIRATE_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "ARE_EMIRATE_HIGHWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "ARE_EMIRATE_HIGHWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "ARE_EMIRATE_HIGHWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "ARE_EMIRATE_HIGHWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "ARE_EMIRATE_HIGHWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "ARE_EMIRATE_HIGHWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "ARE_NATIONAL_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 705, "y": 388 }, "ARE_NATIONAL_HIGHWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 134, "y": 94 }, "ARE_NATIONAL_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 723, "y": 388 }, "ARE_NATIONAL_HIGHWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 158, "y": 94 }, "ARE_NATIONAL_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 0, "y": 422 }, "ARE_NATIONAL_HIGHWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 0, "y": 134 }, "ARE_NATIONAL_HIGHWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 28, "y": 422 }, "ARE_NATIONAL_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 185, "y": 0 }, "ARE_NATIONAL_HIGHWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 64, "y": 422 }, "ARE_NATIONAL_HIGHWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 226, "y": 0 }, "ARE_NATIONAL_HIGHWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 105, "y": 422 }, "ARE_NATIONAL_HIGHWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 274, "y": 0 }, "ARE_NATIONAL_HIGHWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 154, "y": 422 }, "ARE_NATIONAL_HIGHWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 0, "y": 172 }, "ARE_OTHER_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "ARE_OTHER_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "ARE_OTHER_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "ARE_OTHER_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "ARE_OTHER_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "ARE_OTHER_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "ARE_OTHER_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "ARE_OTHER_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "ARE_OTHER_HIGHWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "ARE_OTHER_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "ARE_OTHER_HIGHWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "ARE_OTHER_HIGHWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "ARE_OTHER_HIGHWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "ARE_OTHER_HIGHWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "ARE_OTHER_HIGHWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "ARE_OTHER_HIGHWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "ASIAN_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "ASIAN_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "ASIAN_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "ASIAN_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "ASIAN_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "ASIAN_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "ASIAN_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "ASIAN_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "ASIAN_HIGHWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "ASIAN_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "ASIAN_HIGHWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "ASIAN_HIGHWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "ASIAN_HIGHWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "ASIAN_HIGHWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "ASIAN_HIGHWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "ASIAN_HIGHWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "AUS_METROPOLITAN_ROAD-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 861, "y": 422 }, "AUS_METROPOLITAN_ROAD-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 111, "y": 352 }, "AUS_METROPOLITAN_ROAD-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 881, "y": 422 }, "AUS_METROPOLITAN_ROAD-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 135, "y": 352 }, "AUS_METROPOLITAN_ROAD-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 901, "y": 422 }, "AUS_METROPOLITAN_ROAD-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 159, "y": 352 }, "AUS_METROPOLITAN_ROAD-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 929, "y": 422 }, "AUS_METROPOLITAN_ROAD-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 191, "y": 352 }, "AUS_METROPOLITAN_ROAD-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 965, "y": 422 }, "AUS_METROPOLITAN_ROAD-5-xl": { "height": 34, "pixelRatio": 1, "width": 48, "x": 232, "y": 352 }, "AUS_METROPOLITAN_ROAD-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 1006, "y": 422 }, "AUS_METROPOLITAN_ROAD-6-xl": { "height": 34, "pixelRatio": 1, "width": 56, "x": 280, "y": 352 }, "AUS_METROPOLITAN_ROAD-7-large": { "height": 30, "pixelRatio": 1, "width": 57, "x": 1055, "y": 422 }, "AUS_METROPOLITAN_ROAD-7-xl": { "height": 34, "pixelRatio": 1, "width": 65, "x": 364, "y": 172 }, "AUS_NATIONAL_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 509, "y": 422 }, "AUS_NATIONAL_HIGHWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 32, "y": 134 }, "AUS_NATIONAL_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 527, "y": 422 }, "AUS_NATIONAL_HIGHWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 56, "y": 134 }, "AUS_NATIONAL_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 547, "y": 422 }, "AUS_NATIONAL_HIGHWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 80, "y": 134 }, "AUS_NATIONAL_HIGHWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 575, "y": 422 }, "AUS_NATIONAL_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 65, "y": 172 }, "AUS_NATIONAL_HIGHWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 611, "y": 422 }, "AUS_NATIONAL_HIGHWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 106, "y": 172 }, "AUS_NATIONAL_HIGHWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 652, "y": 422 }, "AUS_NATIONAL_HIGHWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 154, "y": 172 }, "AUS_NATIONAL_HIGHWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 701, "y": 422 }, "AUS_NATIONAL_HIGHWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 210, "y": 172 }, "AUS_NATIONAL_HIGHWAY_ALT-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "AUS_NATIONAL_HIGHWAY_ALT-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "AUS_NATIONAL_HIGHWAY_ALT-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "AUS_NATIONAL_HIGHWAY_ALT-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "AUS_NATIONAL_HIGHWAY_ALT-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "AUS_NATIONAL_HIGHWAY_ALT-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "AUS_NATIONAL_HIGHWAY_ALT-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "AUS_NATIONAL_HIGHWAY_ALT-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "AUS_NATIONAL_HIGHWAY_ALT-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "AUS_NATIONAL_ROAD-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "AUS_NATIONAL_ROAD-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "AUS_NATIONAL_ROAD-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "AUS_NATIONAL_ROAD-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "AUS_NATIONAL_ROAD-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "AUS_NATIONAL_ROAD-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "AUS_NATIONAL_ROAD-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "AUS_NATIONAL_ROAD-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "AUS_NATIONAL_ROAD-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "AUS_NATIONAL_ROAD-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "AUS_NATIONAL_ROAD-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "AUS_NATIONAL_ROAD-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "AUS_NATIONAL_ROAD-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "AUS_NATIONAL_ROAD-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "AUS_STATE_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 231, "y": 454 }, "AUS_STATE_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 121, "y": 208 }, "AUS_STATE_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 24, "x": 253, "y": 454 }, "AUS_STATE_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 147, "y": 208 }, "AUS_STATE_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 32, "x": 277, "y": 454 }, "AUS_STATE_HIGHWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 38, "x": 175, "y": 208 }, "AUS_STATE_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "AUS_STATE_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "AUS_STATE_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "AUS_STATE_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "AUS_STATE_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "AUS_STATE_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "AUS_STATE_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "AUS_STATE_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "AUS_STATE_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "AUS_STATE_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "AUS_STATE_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "AUS_STATE_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "AUS_STATE_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "AUS_STATE_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "AUS_STATE_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "AUS_STATE_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "AUS_TOURIST_DRIVE-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1465, "y": 646 }, "AUS_TOURIST_DRIVE-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 429, "y": 172 }, "AUS_TOURIST_DRIVE-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1487, "y": 646 }, "AUS_TOURIST_DRIVE-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 457, "y": 172 }, "AUS_TOURIST_DRIVE-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 768, "y": 678 }, "AUS_TOURIST_DRIVE-3-xl": { "height": 34, "pixelRatio": 1, "width": 36, "x": 485, "y": 172 }, "AUS_TOURIST_DRIVE-4-large": { "height": 28, "pixelRatio": 1, "width": 40, "x": 798, "y": 678 }, "AUS_TOURIST_DRIVE-4-xl": { "height": 34, "pixelRatio": 1, "width": 47, "x": 521, "y": 172 }, "AUS_TOURIST_DRIVE-5-large": { "height": 30, "pixelRatio": 1, "width": 47, "x": 1112, "y": 422 }, "AUS_TOURIST_DRIVE-5-xl": { "height": 34, "pixelRatio": 1, "width": 54, "x": 568, "y": 172 }, "AUS_TOURIST_DRIVE-6-large": { "height": 30, "pixelRatio": 1, "width": 51, "x": 1159, "y": 422 }, "AUS_TOURIST_DRIVE-6-xl": { "height": 34, "pixelRatio": 1, "width": 60, "x": 622, "y": 172 }, "AUS_TOURIST_DRIVE-7-large": { "height": 30, "pixelRatio": 1, "width": 59, "x": 1210, "y": 422 }, "AUS_TOURIST_DRIVE-7-xl": { "height": 34, "pixelRatio": 1, "width": 69, "x": 682, "y": 172 }, "AUT_AUTOBAHN-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "AUT_AUTOBAHN-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "AUT_AUTOBAHN-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "AUT_AUTOBAHN-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "AUT_AUTOBAHN-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "AUT_AUTOBAHN-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "AUT_AUTOBAHN-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "AUT_AUTOBAHN-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "AUT_AUTOBAHN-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "AUT_AUTOBAHN-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "AUT_AUTOBAHN-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "AUT_AUTOBAHN-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "AUT_AUTOBAHN-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "AUT_AUTOBAHN-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "AUT_AUTOBAHN-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "AUT_AUTOBAHN-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "AUT_BUNDESSTRASSE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "AUT_BUNDESSTRASSE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "AUT_BUNDESSTRASSE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "AUT_BUNDESSTRASSE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "AUT_BUNDESSTRASSE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "AUT_BUNDESSTRASSE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "AUT_BUNDESSTRASSE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "AUT_BUNDESSTRASSE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "AUT_BUNDESSTRASSE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "AUT_BUNDESSTRASSE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "AUT_BUNDESSTRASSE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "AUT_BUNDESSTRASSE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "AUT_BUNDESSTRASSE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "AUT_BUNDESSTRASSE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "AUT_BUNDESSTRASSE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "AUT_BUNDESSTRASSE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "AUT_SCHNELLSTRASSE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "AUT_SCHNELLSTRASSE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "AUT_SCHNELLSTRASSE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "AUT_SCHNELLSTRASSE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "AUT_SCHNELLSTRASSE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "AUT_SCHNELLSTRASSE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "AUT_SCHNELLSTRASSE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "AUT_SCHNELLSTRASSE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "AUT_SCHNELLSTRASSE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "AUT_SCHNELLSTRASSE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "AUT_SCHNELLSTRASSE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "AUT_SCHNELLSTRASSE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "AUT_SCHNELLSTRASSE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "AUT_SCHNELLSTRASSE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "AUT_SCHNELLSTRASSE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "AUT_SCHNELLSTRASSE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "BEL_AUTOROUTE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "BEL_AUTOROUTE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "BEL_AUTOROUTE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "BEL_AUTOROUTE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "BEL_AUTOROUTE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "BEL_AUTOROUTE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "BEL_AUTOROUTE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "BEL_AUTOROUTE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "BEL_AUTOROUTE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "BEL_AUTOROUTE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "BEL_AUTOROUTE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "BEL_AUTOROUTE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "BEL_AUTOROUTE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "BEL_AUTOROUTE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "BEL_AUTOROUTE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "BEL_AUTOROUTE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "BEL_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "BEL_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "BEL_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "BEL_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "BEL_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "BEL_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "BEL_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "BEL_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "BEL_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "BEL_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "BEL_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "BEL_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "BEL_NATIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "BEL_NATIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "BEL_NATIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "BEL_NATIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "BEL_RINGWEG-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "BEL_RINGWEG-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "BEL_RINGWEG-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "BEL_RINGWEG-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "BEL_RINGWEG-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "BEL_RINGWEG-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "BEL_RINGWEG-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "BEL_RINGWEG-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "BEL_RINGWEG-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "BEL_RINGWEG-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "BEL_RINGWEG-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "BEL_RINGWEG-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "BEL_RINGWEG-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "BEL_RINGWEG-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "BEL_RINGWEG-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "BEL_RINGWEG-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "BRA_FEDERAL_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "BRA_FEDERAL_HIGHWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "BRA_FEDERAL_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "BRA_FEDERAL_HIGHWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "BRA_FEDERAL_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "BRA_FEDERAL_HIGHWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "BRA_FEDERAL_HIGHWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "BRA_FEDERAL_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "BRA_FEDERAL_HIGHWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "BRA_FEDERAL_HIGHWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "BRA_FEDERAL_HIGHWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "BRA_FEDERAL_HIGHWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "BRA_FEDERAL_HIGHWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "BRA_FEDERAL_HIGHWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "BRA_STATE_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1132, "y": 678 }, "BRA_STATE_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 382, "y": 208 }, "BRA_STATE_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1154, "y": 678 }, "BRA_STATE_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 410, "y": 208 }, "BRA_STATE_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 1176, "y": 678 }, "BRA_STATE_HIGHWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 36, "x": 438, "y": 208 }, "BRA_STATE_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 40, "x": 1206, "y": 678 }, "BRA_STATE_HIGHWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 47, "x": 474, "y": 208 }, "BRA_STATE_HIGHWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 47, "x": 1269, "y": 422 }, "BRA_STATE_HIGHWAY-5-xl": { "height": 34, "pixelRatio": 1, "width": 54, "x": 521, "y": 208 }, "BRA_STATE_HIGHWAY-6-large": { "height": 30, "pixelRatio": 1, "width": 51, "x": 1316, "y": 422 }, "BRA_STATE_HIGHWAY-6-xl": { "height": 34, "pixelRatio": 1, "width": 60, "x": 575, "y": 208 }, "BRA_STATE_HIGHWAY-7-large": { "height": 30, "pixelRatio": 1, "width": 59, "x": 1367, "y": 422 }, "BRA_STATE_HIGHWAY-7-xl": { "height": 34, "pixelRatio": 1, "width": 69, "x": 635, "y": 208 }, "CAN_AUTOROUTE_QUEBEC-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 705, "y": 388 }, "CAN_AUTOROUTE_QUEBEC-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 134, "y": 94 }, "CAN_AUTOROUTE_QUEBEC-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 723, "y": 388 }, "CAN_AUTOROUTE_QUEBEC-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 158, "y": 94 }, "CAN_AUTOROUTE_QUEBEC-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 0, "y": 422 }, "CAN_AUTOROUTE_QUEBEC-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 0, "y": 134 }, "CAN_AUTOROUTE_QUEBEC-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 28, "y": 422 }, "CAN_AUTOROUTE_QUEBEC-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 185, "y": 0 }, "CAN_AUTOROUTE_QUEBEC-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 64, "y": 422 }, "CAN_AUTOROUTE_QUEBEC-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 226, "y": 0 }, "CAN_AUTOROUTE_QUEBEC-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 105, "y": 422 }, "CAN_AUTOROUTE_QUEBEC-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 274, "y": 0 }, "CAN_AUTOROUTE_QUEBEC-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 154, "y": 422 }, "CAN_AUTOROUTE_QUEBEC-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 0, "y": 172 }, "CAN_PROVINCIAL_ALBERTA-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "CAN_PROVINCIAL_ALBERTA-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "CAN_PROVINCIAL_ALBERTA-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "CAN_PROVINCIAL_ALBERTA-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "CAN_PROVINCIAL_ALBERTA-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "CAN_PROVINCIAL_ALBERTA-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "CAN_PROVINCIAL_ALBERTA-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "CAN_PROVINCIAL_ALBERTA-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "CAN_PROVINCIAL_ALBERTA-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "CAN_PROVINCIAL_BRITISH_COLUMBIA-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "CAN_PROVINCIAL_MANITOBA-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "CAN_PROVINCIAL_MANITOBA-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "CAN_PROVINCIAL_MANITOBA-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "CAN_PROVINCIAL_MANITOBA-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "CAN_PROVINCIAL_MANITOBA-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "CAN_PROVINCIAL_MANITOBA-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "CAN_PROVINCIAL_MANITOBA-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "CAN_PROVINCIAL_MANITOBA-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "CAN_PROVINCIAL_MANITOBA-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "CAN_PROVINCIAL_NEW_BRUNSWICK-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NORTHWEST_TERRITORIES-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NOVASCOTIA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_PROVINCIAL_PRINCE_EDWARD-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "CAN_PROVINCIAL_PRINCE_EDWARD-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "CAN_PROVINCIAL_PRINCE_EDWARD-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "CAN_PROVINCIAL_PRINCE_EDWARD-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "CAN_PROVINCIAL_PRINCE_EDWARD-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "CAN_PROVINCIAL_PRINCE_EDWARD-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "CAN_PROVINCIAL_PRINCE_EDWARD-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "CAN_PROVINCIAL_PRINCE_EDWARD-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "CAN_PROVINCIAL_PRINCE_EDWARD-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "CAN_PROVINCIAL_QUEBEC-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 509, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 32, "y": 134 }, "CAN_PROVINCIAL_QUEBEC-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 527, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 56, "y": 134 }, "CAN_PROVINCIAL_QUEBEC-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 547, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 80, "y": 134 }, "CAN_PROVINCIAL_QUEBEC-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 575, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 65, "y": 172 }, "CAN_PROVINCIAL_QUEBEC-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 611, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 106, "y": 172 }, "CAN_PROVINCIAL_QUEBEC-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 652, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 154, "y": 172 }, "CAN_PROVINCIAL_QUEBEC-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 701, "y": 422 }, "CAN_PROVINCIAL_QUEBEC-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 210, "y": 172 }, "CAN_PROVINCIAL_SASKATCHEWAN-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 705, "y": 388 }, "CAN_PROVINCIAL_SASKATCHEWAN-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 134, "y": 94 }, "CAN_PROVINCIAL_SASKATCHEWAN-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 723, "y": 388 }, "CAN_PROVINCIAL_SASKATCHEWAN-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 158, "y": 94 }, "CAN_PROVINCIAL_SASKATCHEWAN-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 0, "y": 422 }, "CAN_PROVINCIAL_SASKATCHEWAN-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 0, "y": 134 }, "CAN_PROVINCIAL_SASKATCHEWAN-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 28, "y": 422 }, "CAN_PROVINCIAL_SASKATCHEWAN-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 185, "y": 0 }, "CAN_PROVINCIAL_SASKATCHEWAN-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 64, "y": 422 }, "CAN_PROVINCIAL_SASKATCHEWAN-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 226, "y": 0 }, "CAN_PROVINCIAL_SASKATCHEWAN-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 105, "y": 422 }, "CAN_PROVINCIAL_SASKATCHEWAN-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 274, "y": 0 }, "CAN_PROVINCIAL_SASKATCHEWAN-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 154, "y": 422 }, "CAN_PROVINCIAL_SASKATCHEWAN-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 0, "y": 172 }, "CAN_PROVINCIAL_YUKON-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1246, "y": 678 }, "CAN_PROVINCIAL_YUKON-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 672, "y": 454 }, "CAN_PROVINCIAL_YUKON-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1264, "y": 678 }, "CAN_PROVINCIAL_YUKON-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 694, "y": 454 }, "CAN_PROVINCIAL_YUKON-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1284, "y": 678 }, "CAN_PROVINCIAL_YUKON-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 718, "y": 454 }, "CAN_PROVINCIAL_YUKON-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1312, "y": 678 }, "CAN_PROVINCIAL_YUKON-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 0, "y": 486 }, "CAN_PROVINCIAL_YUKON-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1348, "y": 678 }, "CAN_PROVINCIAL_YUKON-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 41, "y": 486 }, "CAN_PROVINCIAL_YUKON-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1389, "y": 678 }, "CAN_PROVINCIAL_YUKON-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 89, "y": 486 }, "CAN_PROVINCIAL_YUKON-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1438, "y": 678 }, "CAN_PROVINCIAL_YUKON-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 145, "y": 486 }, "CAN_PROVINCIAL_YUKON-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 755, "y": 710 }, "CAN_PROVINCIAL_YUKON-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 210, "y": 486 }, "CAN_TRANS_CANADA_HIGHWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1426, "y": 422 }, "CAN_TRANS_CANADA_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 704, "y": 208 }, "CAN_TRANS_CANADA_HIGHWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1448, "y": 422 }, "CAN_TRANS_CANADA_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 730, "y": 208 }, "CAN_TRANS_CANADA_HIGHWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 32, "x": 1476, "y": 422 }, "CAN_TRANS_CANADA_HIGHWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 40, "x": 375, "y": 244 }, "CHE_AUTOBAHN-1-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1495, "y": 678 }, "CHE_AUTOBAHN-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1508, "y": 422 }, "CHE_AUTOBAHN-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 818, "y": 710 }, "CHE_AUTOBAHN-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 768, "y": 454 }, "CHE_AUTOBAHN-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 840, "y": 710 }, "CHE_AUTOBAHN-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 794, "y": 454 }, "CHE_AUTOBAHN-4-large": { "height": 28, "pixelRatio": 1, "width": 38, "x": 870, "y": 710 }, "CHE_AUTOBAHN-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 828, "y": 454 }, "CHE_KANTONSSTRASSE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "CHE_KANTONSSTRASSE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "CHE_KANTONSSTRASSE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "CHE_KANTONSSTRASSE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "CHE_KANTONSSTRASSE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "CHE_KANTONSSTRASSE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "CHE_KANTONSSTRASSE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "CHE_KANTONSSTRASSE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "CHE_KANTONSSTRASSE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "CHE_KANTONSSTRASSE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "CHE_KANTONSSTRASSE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "CHE_KANTONSSTRASSE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "CHE_KANTONSSTRASSE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "CHE_KANTONSSTRASSE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "CHE_KANTONSSTRASSE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "CHE_KANTONSSTRASSE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "CHL_FEDERAL_HIGHWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 871, "y": 454 }, "CHL_FEDERAL_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 285, "y": 486 }, "CHL_FEDERAL_HIGHWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 893, "y": 454 }, "CHL_FEDERAL_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 309, "y": 486 }, "CHL_FEDERAL_HIGHWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 915, "y": 454 }, "CHL_FEDERAL_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 333, "y": 486 }, "CHL_FEDERAL_HIGHWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 945, "y": 454 }, "CHL_FEDERAL_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 365, "y": 486 }, "CHL_FEDERAL_HIGHWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 43, "x": 983, "y": 454 }, "CHL_FEDERAL_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 406, "y": 486 }, "CHL_STATE_HIGHWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1026, "y": 454 }, "CHL_STATE_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 454, "y": 486 }, "CHL_STATE_HIGHWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1048, "y": 454 }, "CHL_STATE_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 478, "y": 486 }, "CHL_STATE_HIGHWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 1070, "y": 454 }, "CHL_STATE_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 502, "y": 486 }, "CHL_STATE_HIGHWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1100, "y": 454 }, "CHL_STATE_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 534, "y": 486 }, "CHL_STATE_HIGHWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 43, "x": 1138, "y": 454 }, "CHL_STATE_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 575, "y": 486 }, "DEU_AUTOBAHN-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1181, "y": 454 }, "DEU_AUTOBAHN-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 415, "y": 244 }, "DEU_AUTOBAHN-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1201, "y": 454 }, "DEU_AUTOBAHN-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 439, "y": 244 }, "DEU_AUTOBAHN-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1221, "y": 454 }, "DEU_AUTOBAHN-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 463, "y": 244 }, "DEU_AUTOBAHN-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1249, "y": 454 }, "DEU_AUTOBAHN-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 495, "y": 244 }, "DEU_AUTOBAHN-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 1285, "y": 454 }, "DEU_AUTOBAHN-5-xl": { "height": 34, "pixelRatio": 1, "width": 48, "x": 536, "y": 244 }, "DEU_AUTOBAHN-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 1326, "y": 454 }, "DEU_AUTOBAHN-6-xl": { "height": 34, "pixelRatio": 1, "width": 56, "x": 584, "y": 244 }, "DEU_AUTOBAHN-7-large": { "height": 30, "pixelRatio": 1, "width": 57, "x": 1375, "y": 454 }, "DEU_AUTOBAHN-7-xl": { "height": 34, "pixelRatio": 1, "width": 65, "x": 640, "y": 244 }, "DEU_BUNDESSTRASSE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "DEU_BUNDESSTRASSE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "DEU_BUNDESSTRASSE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "DEU_BUNDESSTRASSE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "DEU_BUNDESSTRASSE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "DEU_BUNDESSTRASSE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "DEU_BUNDESSTRASSE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "DEU_BUNDESSTRASSE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "DEU_BUNDESSTRASSE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "DEU_BUNDESSTRASSE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "DEU_BUNDESSTRASSE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "DEU_BUNDESSTRASSE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "DEU_BUNDESSTRASSE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "DEU_BUNDESSTRASSE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "DEU_BUNDESSTRASSE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "DEU_BUNDESSTRASSE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "DNK_PRIMARY_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "DNK_PRIMARY_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "DNK_PRIMARY_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "DNK_PRIMARY_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "DNK_PRIMARY_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "DNK_PRIMARY_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "DNK_PRIMARY_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "DNK_PRIMARY_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "DNK_PRIMARY_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "DNK_PRIMARY_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "DNK_PRIMARY_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "DNK_PRIMARY_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "DNK_PRIMARY_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "DNK_PRIMARY_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "DNK_PRIMARY_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "DNK_PRIMARY_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "ESP_AUTOPISTA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "ESP_AUTOPISTA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "ESP_AUTOPISTA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "ESP_AUTOPISTA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "ESP_AUTOPISTA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "ESP_AUTOPISTA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "ESP_AUTOPISTA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "ESP_AUTOPISTA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "ESP_AUTOPISTA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "ESP_AUTOPISTA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "ESP_AUTOPISTA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "ESP_AUTOPISTA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "ESP_AUTOPISTA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "ESP_AUTOPISTA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "ESP_AUTOPISTA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "ESP_AUTOPISTA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1161, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 742, "y": 486 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1179, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 244, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1199, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 268, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1227, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 300, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1263, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 341, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1304, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 389, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1353, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 445, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1410, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_ORANGE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 510, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_RED-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_RED-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "ESP_CARRETERA_AUTONOMICA_RED-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_RED-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_RED-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "ESP_CARRETERA_AUTONOMICA_RED-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "ESP_CARRETERA_AUTONOMICA_RED-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "ESP_CARRETERA_AUTONOMICA_RED-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_RED-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "ESP_CARRETERA_AUTONOMICA_RED-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "ESP_CARRETERA_AUTONOMICA_RED-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "ESP_CARRETERA_AUTONOMICA_RED-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_RED-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "ESP_CARRETERA_AUTONOMICA_RED-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "ESP_CARRETERA_AUTONOMICA_RED-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "ESP_CARRETERA_AUTONOMICA_RED-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "ESP_CARRETERA_AUTONOMICA_YELLOW-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "ESP_CARRETERA_RIGE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "ESP_CARRETERA_RIGE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "ESP_CARRETERA_RIGE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "ESP_CARRETERA_RIGE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "ESP_CARRETERA_RIGE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "ESP_CARRETERA_RIGE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "ESP_CARRETERA_RIGE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "ESP_CARRETERA_RIGE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "ESP_CARRETERA_RIGE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "ESP_CARRETERA_RIGE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "ESP_CARRETERA_RIGE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "ESP_CARRETERA_RIGE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "ESP_CARRETERA_RIGE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "ESP_CARRETERA_RIGE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "ESP_CARRETERA_RIGE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "ESP_CARRETERA_RIGE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "EST_MAIN_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "EST_MAIN_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "EST_MAIN_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "EST_MAIN_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "EST_MAIN_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "EST_MAIN_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "EST_MAIN_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "EST_MAIN_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "EST_MAIN_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "EST_MAIN_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "EST_MAIN_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "EST_MAIN_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "EST_MAIN_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "EST_MAIN_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "EST_MAIN_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "EST_MAIN_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "EST_STATE_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "EST_STATE_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "EST_STATE_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "EST_STATE_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "EST_STATE_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "EST_STATE_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "EST_STATE_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "EST_STATE_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "EST_STATE_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "EST_STATE_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "EST_STATE_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "EST_STATE_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "EST_STATE_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "EST_STATE_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "EST_STATE_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "EST_STATE_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "EUROPEAN_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "EUROPEAN_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "EUROPEAN_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "EUROPEAN_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "EUROPEAN_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "EUROPEAN_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "EUROPEAN_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "EUROPEAN_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "EUROPEAN_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "EUROPEAN_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "EUROPEAN_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "EUROPEAN_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "EUROPEAN_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "EUROPEAN_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "EUROPEAN_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "EUROPEAN_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "FIN_KANTATIE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "FIN_KANTATIE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "FIN_KANTATIE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "FIN_KANTATIE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "FIN_KANTATIE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "FIN_KANTATIE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "FIN_KANTATIE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "FIN_KANTATIE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "FIN_KANTATIE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "FIN_KANTATIE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "FIN_KANTATIE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "FIN_KANTATIE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "FIN_KANTATIE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "FIN_KANTATIE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "FIN_KANTATIE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "FIN_KANTATIE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "FIN_VALTATIE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "FIN_VALTATIE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "FIN_VALTATIE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "FIN_VALTATIE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "FIN_VALTATIE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "FIN_VALTATIE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "FIN_VALTATIE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "FIN_VALTATIE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "FIN_VALTATIE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "FIN_VALTATIE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "FIN_VALTATIE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "FIN_VALTATIE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "FIN_VALTATIE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "FIN_VALTATIE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "FIN_VALTATIE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "FIN_VALTATIE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "FIN_YHDYSTIE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "FIN_YHDYSTIE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "FIN_YHDYSTIE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "FIN_YHDYSTIE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "FIN_YHDYSTIE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "FIN_YHDYSTIE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "FIN_YHDYSTIE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "FIN_YHDYSTIE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "FIN_YHDYSTIE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "FIN_YHDYSTIE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "FIN_YHDYSTIE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "FIN_YHDYSTIE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "FIN_YHDYSTIE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "FIN_YHDYSTIE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "FIN_YHDYSTIE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "FIN_YHDYSTIE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "FRA_AUTOROUTE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "FRA_AUTOROUTE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "FRA_AUTOROUTE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "FRA_AUTOROUTE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "FRA_AUTOROUTE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "FRA_AUTOROUTE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "FRA_AUTOROUTE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "FRA_AUTOROUTE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "FRA_AUTOROUTE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "FRA_AUTOROUTE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "FRA_AUTOROUTE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "FRA_AUTOROUTE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "FRA_AUTOROUTE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "FRA_AUTOROUTE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "FRA_AUTOROUTE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "FRA_AUTOROUTE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "FRA_DEPARTMENTAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "FRA_DEPARTMENTAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "FRA_DEPARTMENTAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "FRA_DEPARTMENTAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "FRA_DEPARTMENTAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "FRA_DEPARTMENTAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "FRA_DEPARTMENTAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "FRA_DEPARTMENTAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "FRA_DEPARTMENTAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "FRA_DEPARTMENTAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "FRA_DEPARTMENTAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "FRA_METROPOLITAN_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "FRA_METROPOLITAN_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "FRA_METROPOLITAN_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "FRA_METROPOLITAN_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "FRA_METROPOLITAN_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "FRA_METROPOLITAN_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "FRA_METROPOLITAN_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "FRA_METROPOLITAN_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "FRA_METROPOLITAN_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "FRA_METROPOLITAN_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "FRA_METROPOLITAN_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "FRA_METROPOLITAN_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "FRA_METROPOLITAN_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "FRA_METROPOLITAN_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "FRA_METROPOLITAN_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "FRA_METROPOLITAN_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "FRA_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "FRA_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "FRA_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "FRA_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "FRA_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "FRA_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "FRA_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "FRA_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "FRA_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "FRA_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "FRA_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "FRA_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "FRA_NATIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "FRA_NATIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "FRA_NATIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "FRA_NATIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "GBR_MOTORWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "GBR_MOTORWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "GBR_MOTORWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "GBR_MOTORWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "GBR_MOTORWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "GBR_MOTORWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "GBR_MOTORWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "GBR_MOTORWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "GBR_MOTORWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "GBR_MOTORWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "GBR_MOTORWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "GBR_MOTORWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "GBR_MOTORWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "GBR_MOTORWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "GBR_MOTORWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "GBR_MOTORWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "GBR_PRIMARY_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "GBR_PRIMARY_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "GBR_PRIMARY_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "GBR_PRIMARY_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "GBR_PRIMARY_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "GBR_PRIMARY_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "GBR_PRIMARY_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "GBR_PRIMARY_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "GBR_PRIMARY_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "GBR_PRIMARY_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "GBR_PRIMARY_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "GBR_PRIMARY_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "GBR_PRIMARY_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "GBR_PRIMARY_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "GBR_PRIMARY_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "GBR_PRIMARY_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "GRC_MOTORWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1432, "y": 454 }, "GRC_MOTORWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 705, "y": 244 }, "GRC_MOTORWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1452, "y": 454 }, "GRC_MOTORWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 729, "y": 244 }, "GRC_MOTORWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1472, "y": 454 }, "GRC_MOTORWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 370, "y": 280 }, "GRC_MOTORWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1500, "y": 454 }, "GRC_MOTORWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 402, "y": 280 }, "GRC_MOTORWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 764, "y": 486 }, "GRC_MOTORWAY-5-xl": { "height": 34, "pixelRatio": 1, "width": 48, "x": 443, "y": 280 }, "GRC_MOTORWAY-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 805, "y": 486 }, "GRC_MOTORWAY-6-xl": { "height": 34, "pixelRatio": 1, "width": 56, "x": 491, "y": 280 }, "GRC_MOTORWAY-7-large": { "height": 30, "pixelRatio": 1, "width": 57, "x": 854, "y": 486 }, "GRC_MOTORWAY-7-xl": { "height": 34, "pixelRatio": 1, "width": 65, "x": 547, "y": 280 }, "GRC_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "GRC_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "GRC_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "GRC_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "GRC_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "GRC_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "GRC_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "GRC_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "GRC_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "GRC_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "GRC_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "GRC_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "GRC_NATIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "GRC_NATIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "GRC_NATIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "GRC_NATIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "HUN_FREEWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 705, "y": 388 }, "HUN_FREEWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 134, "y": 94 }, "HUN_FREEWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 723, "y": 388 }, "HUN_FREEWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 158, "y": 94 }, "HUN_FREEWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 0, "y": 422 }, "HUN_FREEWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 0, "y": 134 }, "HUN_FREEWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 28, "y": 422 }, "HUN_FREEWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 185, "y": 0 }, "HUN_FREEWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 64, "y": 422 }, "HUN_FREEWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 226, "y": 0 }, "HUN_FREEWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 105, "y": 422 }, "HUN_FREEWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 274, "y": 0 }, "HUN_FREEWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 154, "y": 422 }, "HUN_FREEWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 0, "y": 172 }, "HUN_PRIMARY_SECONDARY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 509, "y": 422 }, "HUN_PRIMARY_SECONDARY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 32, "y": 134 }, "HUN_PRIMARY_SECONDARY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 527, "y": 422 }, "HUN_PRIMARY_SECONDARY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 56, "y": 134 }, "HUN_PRIMARY_SECONDARY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 547, "y": 422 }, "HUN_PRIMARY_SECONDARY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 80, "y": 134 }, "HUN_PRIMARY_SECONDARY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 575, "y": 422 }, "HUN_PRIMARY_SECONDARY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 65, "y": 172 }, "HUN_PRIMARY_SECONDARY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 611, "y": 422 }, "HUN_PRIMARY_SECONDARY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 106, "y": 172 }, "HUN_PRIMARY_SECONDARY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 652, "y": 422 }, "HUN_PRIMARY_SECONDARY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 154, "y": 172 }, "HUN_PRIMARY_SECONDARY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 701, "y": 422 }, "HUN_PRIMARY_SECONDARY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 210, "y": 172 }, "IDN_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 24, "x": 1511, "y": 710 }, "IDN_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 706, "y": 518 }, "IDN_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 26, "x": 1016, "y": 742 }, "IDN_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 30, "x": 734, "y": 518 }, "IDN_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1042, "y": 742 }, "IDN_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 38, "x": 205, "y": 550 }, "IDN_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 42, "x": 1076, "y": 742 }, "IDN_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 47, "x": 243, "y": 550 }, "IDN_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 47, "x": 1118, "y": 742 }, "IDN_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 54, "x": 290, "y": 550 }, "IDN_PROVINCIAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 24, "x": 1511, "y": 710 }, "IDN_PROVINCIAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 706, "y": 518 }, "IDN_PROVINCIAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 26, "x": 1016, "y": 742 }, "IDN_PROVINCIAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 30, "x": 734, "y": 518 }, "IDN_PROVINCIAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1042, "y": 742 }, "IDN_PROVINCIAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 38, "x": 205, "y": 550 }, "IDN_PROVINCIAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 42, "x": 1076, "y": 742 }, "IDN_PROVINCIAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 47, "x": 243, "y": 550 }, "IDN_PROVINCIAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 47, "x": 1118, "y": 742 }, "IDN_PROVINCIAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 54, "x": 290, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 750, "y": 454 }, "IND_NATIONAL_EXPRESSWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 192, "y": 134 }, "IND_NATIONAL_EXPRESSWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 344, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 216, "y": 134 }, "IND_NATIONAL_EXPRESSWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 364, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 240, "y": 134 }, "IND_NATIONAL_EXPRESSWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 392, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 308, "y": 244 }, "IND_NATIONAL_EXPRESSWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 428, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 213, "y": 208 }, "IND_NATIONAL_EXPRESSWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 469, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 261, "y": 208 }, "IND_NATIONAL_EXPRESSWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 518, "y": 550 }, "IND_NATIONAL_EXPRESSWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 317, "y": 208 }, "IND_NATIONAL_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 743, "y": 388 }, "IND_NATIONAL_HIGHWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 112, "y": 134 }, "IND_NATIONAL_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 0, "y": 454 }, "IND_NATIONAL_HIGHWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 136, "y": 134 }, "IND_NATIONAL_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 20, "y": 454 }, "IND_NATIONAL_HIGHWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 160, "y": 134 }, "IND_NATIONAL_HIGHWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 48, "y": 454 }, "IND_NATIONAL_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 275, "y": 172 }, "IND_NATIONAL_HIGHWAY-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 84, "y": 454 }, "IND_NATIONAL_HIGHWAY-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 316, "y": 172 }, "IND_NATIONAL_HIGHWAY-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 125, "y": 454 }, "IND_NATIONAL_HIGHWAY-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 0, "y": 208 }, "IND_NATIONAL_HIGHWAY-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 174, "y": 454 }, "IND_NATIONAL_HIGHWAY-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 56, "y": 208 }, "IND_STATE_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 575, "y": 550 }, "IND_STATE_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 357, "y": 94 }, "IND_STATE_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 24, "x": 597, "y": 550 }, "IND_STATE_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 345, "y": 50 }, "IND_STATE_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 32, "x": 621, "y": 550 }, "IND_STATE_HIGHWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 38, "x": 330, "y": 0 }, "IRL_MOTORWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "IRL_MOTORWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "IRL_MOTORWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "IRL_MOTORWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "IRL_MOTORWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "IRL_MOTORWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "IRL_MOTORWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "IRL_MOTORWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "IRL_MOTORWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "IRL_MOTORWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "IRL_MOTORWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "IRL_MOTORWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "IRL_MOTORWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "IRL_MOTORWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "IRL_MOTORWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "IRL_MOTORWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "IRL_PRIMARY_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "IRL_PRIMARY_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "IRL_PRIMARY_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "IRL_PRIMARY_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "IRL_PRIMARY_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "IRL_PRIMARY_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "IRL_PRIMARY_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "IRL_PRIMARY_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "IRL_PRIMARY_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "IRL_PRIMARY_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "IRL_PRIMARY_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "IRL_PRIMARY_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "IRL_PRIMARY_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "IRL_PRIMARY_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "IRL_PRIMARY_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "IRL_PRIMARY_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "ISR_INNER_CITY_ROAD-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 911, "y": 486 }, "ISR_INNER_CITY_ROAD-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 931, "y": 486 }, "ISR_INNER_CITY_ROAD-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 953, "y": 486 }, "ISR_INNER_CITY_ROAD-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 975, "y": 486 }, "ISR_INNER_CITY_ROAD-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1001, "y": 486 }, "ISR_INNER_CITY_ROAD-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1029, "y": 486 }, "ISR_INNER_CITY_ROAD-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1063, "y": 486 }, "ISR_INNER_CITY_ROAD-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 1099, "y": 486 }, "ISR_NATIONAL_ROAD-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1142, "y": 486 }, "ISR_NATIONAL_ROAD-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1162, "y": 486 }, "ISR_NATIONAL_ROAD-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1184, "y": 486 }, "ISR_NATIONAL_ROAD-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1206, "y": 486 }, "ISR_NATIONAL_ROAD-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1232, "y": 486 }, "ISR_NATIONAL_ROAD-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1260, "y": 486 }, "ISR_NATIONAL_ROAD-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1294, "y": 486 }, "ISR_NATIONAL_ROAD-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 1330, "y": 486 }, "ISR_REGIONAL_ROAD-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1373, "y": 486 }, "ISR_REGIONAL_ROAD-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1393, "y": 486 }, "ISR_REGIONAL_ROAD-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1415, "y": 486 }, "ISR_REGIONAL_ROAD-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1437, "y": 486 }, "ISR_REGIONAL_ROAD-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1463, "y": 486 }, "ISR_REGIONAL_ROAD-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1491, "y": 486 }, "ISR_REGIONAL_ROAD-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 764, "y": 518 }, "ISR_REGIONAL_ROAD-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 800, "y": 518 }, "ITA_AUTOSTRADA-1-large": { "height": 30, "pixelRatio": 1, "width": 18, "x": 843, "y": 518 }, "ITA_AUTOSTRADA-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 685, "y": 550 }, "ITA_AUTOSTRADA-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 861, "y": 518 }, "ITA_AUTOSTRADA-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 709, "y": 550 }, "ITA_AUTOSTRADA-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 881, "y": 518 }, "ITA_AUTOSTRADA-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 0, "y": 582 }, "ITA_AUTOSTRADA-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 909, "y": 518 }, "ITA_AUTOSTRADA-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 34, "y": 582 }, "ITA_AUTOSTRADA-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 945, "y": 518 }, "ITA_AUTOSTRADA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 77, "y": 582 }, "ITA_AUTOSTRADA-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 986, "y": 518 }, "ITA_AUTOSTRADA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 125, "y": 582 }, "ITA_STATE_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "ITA_STATE_HIGHWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "ITA_STATE_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "ITA_STATE_HIGHWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "ITA_STATE_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "ITA_STATE_HIGHWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "ITA_STATE_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "ITA_STATE_HIGHWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "ITA_STATE_HIGHWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "ITA_STATE_HIGHWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "ITA_STATE_HIGHWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "ITA_STATE_HIGHWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "ITA_STATE_HIGHWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "ITA_STATE_HIGHWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "ITA_STATE_HIGHWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "ITA_STATE_HIGHWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "ITA_TRAFORO-1-large": { "height": 30, "pixelRatio": 1, "width": 18, "x": 843, "y": 518 }, "ITA_TRAFORO-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 685, "y": 550 }, "ITA_TRAFORO-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 861, "y": 518 }, "ITA_TRAFORO-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 709, "y": 550 }, "ITA_TRAFORO-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 881, "y": 518 }, "ITA_TRAFORO-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 0, "y": 582 }, "ITA_TRAFORO-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 909, "y": 518 }, "ITA_TRAFORO-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 34, "y": 582 }, "ITA_TRAFORO-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 945, "y": 518 }, "ITA_TRAFORO-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 77, "y": 582 }, "ITA_TRAFORO-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 986, "y": 518 }, "ITA_TRAFORO-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 125, "y": 582 }, "JPN_NATIONAL_ROAD-1-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 612, "y": 280 }, "JPN_NATIONAL_ROAD-1-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 272, "y": 134 }, "JPN_NATIONAL_ROAD-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 634, "y": 280 }, "JPN_NATIONAL_ROAD-2-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 300, "y": 134 }, "JPN_NATIONAL_ROAD-3-large": { "height": 34, "pixelRatio": 1, "width": 32, "x": 656, "y": 280 }, "JPN_NATIONAL_ROAD-3-xl": { "height": 38, "pixelRatio": 1, "width": 38, "x": 319, "y": 94 }, "JPN_REGIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 24, "x": 1165, "y": 742 }, "JPN_REGIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 735, "y": 550 }, "JPN_REGIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 26, "x": 1189, "y": 742 }, "JPN_REGIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 30, "x": 181, "y": 582 }, "JPN_REGIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1215, "y": 742 }, "JPN_REGIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 38, "x": 211, "y": 582 }, "JPN_REGIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 42, "x": 1249, "y": 742 }, "JPN_REGIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 47, "x": 249, "y": 582 }, "JPN_REGIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 47, "x": 1291, "y": 742 }, "JPN_REGIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 54, "x": 296, "y": 582 }, "JPN_URBAN_EXPRESSWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 350, "y": 582 }, "JPN_URBAN_EXPRESSWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 0, "y": 244 }, "JPN_URBAN_EXPRESSWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 24, "x": 372, "y": 582 }, "JPN_URBAN_EXPRESSWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 26, "y": 244 }, "JPN_URBAN_EXPRESSWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 32, "x": 396, "y": 582 }, "JPN_URBAN_EXPRESSWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 38, "x": 54, "y": 244 }, "KOR_EXPRESS_HIGHWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1035, "y": 518 }, "KOR_EXPRESS_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 688, "y": 280 }, "KOR_EXPRESS_HIGHWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1057, "y": 518 }, "KOR_EXPRESS_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 714, "y": 280 }, "KOR_EXPRESS_HIGHWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 1079, "y": 518 }, "KOR_EXPRESS_HIGHWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 34, "x": 384, "y": 316 }, "KOR_EXPRESS_HIGHWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1109, "y": 518 }, "KOR_EXPRESS_HIGHWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 43, "x": 418, "y": 316 }, "KOR_MOTORWAY-1-large": { "height": 26, "pixelRatio": 1, "width": 22, "x": 1503, "y": 244 }, "KOR_MOTORWAY-1-xl": { "height": 28, "pixelRatio": 1, "width": 24, "x": 1338, "y": 742 }, "KOR_MOTORWAY-2-large": { "height": 26, "pixelRatio": 1, "width": 26, "x": 760, "y": 280 }, "KOR_MOTORWAY-2-xl": { "height": 28, "pixelRatio": 1, "width": 30, "x": 1362, "y": 742 }, "KOR_MOTORWAY-3-large": { "height": 26, "pixelRatio": 1, "width": 34, "x": 786, "y": 280 }, "KOR_MOTORWAY-3-xl": { "height": 28, "pixelRatio": 1, "width": 38, "x": 1392, "y": 742 }, "KOR_MOTORWAY-4-large": { "height": 26, "pixelRatio": 1, "width": 42, "x": 820, "y": 280 }, "KOR_MOTORWAY-4-xl": { "height": 28, "pixelRatio": 1, "width": 47, "x": 1430, "y": 742 }, "KOR_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1477, "y": 742 }, "KOR_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 428, "y": 582 }, "KOR_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1495, "y": 742 }, "KOR_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 450, "y": 582 }, "KOR_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 761, "y": 388 }, "KOR_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 476, "y": 582 }, "KOR_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 38, "x": 791, "y": 388 }, "KOR_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 510, "y": 582 }, "KOR_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 43, "x": 829, "y": 388 }, "KOR_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 50, "x": 553, "y": 582 }, "KOR_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 51, "x": 872, "y": 388 }, "KOR_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 58, "x": 603, "y": 582 }, "LTU_MAIN_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "LTU_MAIN_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "LTU_MAIN_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "LTU_MAIN_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "LTU_MAIN_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "LTU_MAIN_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "LTU_MAIN_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "LTU_MAIN_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "LTU_MAIN_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "LTU_MAIN_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "LTU_MAIN_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "LTU_MAIN_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "LTU_MAIN_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "LTU_MAIN_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "LTU_MAIN_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "LTU_MAIN_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "LTU_STATE_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "LTU_STATE_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "LTU_STATE_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "LTU_STATE_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "LTU_STATE_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "LTU_STATE_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "LTU_STATE_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "LTU_STATE_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "LTU_STATE_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "LTU_STATE_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "LTU_STATE_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "LTU_STATE_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "LTU_STATE_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "LTU_STATE_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "LTU_STATE_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "LTU_STATE_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "MEX_FEDERAL_HIGHWAY-1-large": { "height": 34, "pixelRatio": 1, "width": 20, "x": 740, "y": 280 }, "MEX_FEDERAL_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 92, "y": 244 }, "MEX_FEDERAL_HIGHWAY-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 461, "y": 316 }, "MEX_FEDERAL_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 118, "y": 244 }, "MEX_FEDERAL_HIGHWAY-3-large": { "height": 34, "pixelRatio": 1, "width": 30, "x": 483, "y": 316 }, "MEX_FEDERAL_HIGHWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 36, "x": 328, "y": 134 }, "MEX_FEDERAL_HIGHWAY-4-large": { "height": 36, "pixelRatio": 1, "width": 36, "x": 144, "y": 244 }, "MEX_FEDERAL_HIGHWAY-4-xl": { "height": 38, "pixelRatio": 1, "width": 43, "x": 182, "y": 94 }, "MEX_MEXICO_CITY_EJE_VIAL-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "MEX_MEXICO_CITY_EJE_VIAL-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "MEX_MEXICO_CITY_EJE_VIAL-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "MEX_MEXICO_CITY_EJE_VIAL-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "MEX_MEXICO_CITY_EJE_VIAL-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "MEX_MONTERREY_EJE_METROPOLITANO-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "MEX_MONTERREY_EJE_METROPOLITANO-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "MEX_MONTERREY_EJE_METROPOLITANO-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "MEX_MONTERREY_EJE_METROPOLITANO-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "MEX_STATE_HIGHWAY-1-large": { "height": 34, "pixelRatio": 1, "width": 18, "x": 513, "y": 316 }, "MEX_STATE_HIGHWAY-1-xl": { "height": 40, "pixelRatio": 1, "width": 22, "x": 163, "y": 50 }, "MEX_STATE_HIGHWAY-2-large": { "height": 34, "pixelRatio": 1, "width": 20, "x": 531, "y": 316 }, "MEX_STATE_HIGHWAY-2-xl": { "height": 40, "pixelRatio": 1, "width": 24, "x": 129, "y": 0 }, "MEX_STATE_HIGHWAY-3-large": { "height": 34, "pixelRatio": 1, "width": 28, "x": 551, "y": 316 }, "MEX_STATE_HIGHWAY-3-xl": { "height": 40, "pixelRatio": 1, "width": 32, "x": 153, "y": 0 }, "MEX_STATE_HIGHWAY-4-large": { "height": 36, "pixelRatio": 1, "width": 36, "x": 180, "y": 244 }, "MEX_STATE_HIGHWAY-4-xl": { "height": 42, "pixelRatio": 1, "width": 41, "x": 82, "y": 50 }, "MYS_EXPRESSWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1147, "y": 518 }, "MYS_EXPRESSWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 579, "y": 316 }, "MYS_EXPRESSWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1167, "y": 518 }, "MYS_EXPRESSWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 603, "y": 316 }, "MYS_EXPRESSWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1187, "y": 518 }, "MYS_EXPRESSWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 627, "y": 316 }, "MYS_EXPRESSWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1215, "y": 518 }, "MYS_EXPRESSWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 659, "y": 316 }, "MYS_EXPRESSWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 1251, "y": 518 }, "MYS_EXPRESSWAY-5-xl": { "height": 34, "pixelRatio": 1, "width": 48, "x": 700, "y": 316 }, "MYS_EXPRESSWAY-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 1292, "y": 518 }, "MYS_EXPRESSWAY-6-xl": { "height": 34, "pixelRatio": 1, "width": 56, "x": 336, "y": 352 }, "MYS_EXPRESSWAY-7-large": { "height": 30, "pixelRatio": 1, "width": 57, "x": 1341, "y": 518 }, "MYS_EXPRESSWAY-7-xl": { "height": 34, "pixelRatio": 1, "width": 65, "x": 392, "y": 352 }, "NLD_AUTOSNELWEG-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "NLD_AUTOSNELWEG-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "NLD_AUTOSNELWEG-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "NLD_AUTOSNELWEG-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "NLD_AUTOSNELWEG-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "NLD_AUTOSNELWEG-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "NLD_AUTOSNELWEG-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "NLD_AUTOSNELWEG-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "NLD_AUTOSNELWEG-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "NLD_AUTOSNELWEG-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "NLD_AUTOSNELWEG-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "NLD_AUTOSNELWEG-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "NLD_AUTOSNELWEG-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "NLD_AUTOSNELWEG-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "NLD_AUTOSNELWEG-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "NLD_AUTOSNELWEG-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "NLD_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "NLD_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "NLD_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "NLD_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "NLD_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "NLD_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "NLD_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "NLD_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "NLD_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "NLD_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "NLD_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "NLD_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "NLD_NATIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "NLD_NATIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "NLD_NATIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "NLD_NATIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "NLD_ONTSLUITINGS_ROAD-4-large": { "height": 26, "pixelRatio": 1, "width": 34, "x": 862, "y": 280 }, "NLD_ONTSLUITINGS_ROAD-4-xl": { "height": 28, "pixelRatio": 1, "width": 39, "x": 923, "y": 388 }, "NOR_RIKSVEG-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "NOR_RIKSVEG-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "NOR_RIKSVEG-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "NOR_RIKSVEG-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "NOR_RIKSVEG-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "NOR_RIKSVEG-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "NOR_RIKSVEG-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "NOR_RIKSVEG-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "NOR_RIKSVEG-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "NOR_RIKSVEG-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "NOR_RIKSVEG-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "NOR_RIKSVEG-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "NOR_RIKSVEG-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "NOR_RIKSVEG-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "NOR_RIKSVEG-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "NOR_RIKSVEG-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "NOR_RING_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1517, "y": 742 }, "NOR_RING_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 715, "y": 582 }, "NOR_RING_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 962, "y": 388 }, "NOR_RING_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 737, "y": 582 }, "NOR_RING_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 984, "y": 388 }, "NOR_RING_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 0, "y": 614 }, "NOR_RING_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 38, "x": 1014, "y": 388 }, "NOR_RING_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 34, "y": 614 }, "NOR_RING_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 43, "x": 1052, "y": 388 }, "NOR_RING_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 50, "x": 77, "y": 614 }, "NOR_RING_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 51, "x": 1095, "y": 388 }, "NOR_RING_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 58, "x": 127, "y": 614 }, "NZL_STATE_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 185, "y": 614 }, "NZL_STATE_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 216, "y": 244 }, "NZL_STATE_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 24, "x": 207, "y": 614 }, "NZL_STATE_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 242, "y": 244 }, "NZL_STATE_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 32, "x": 231, "y": 614 }, "NZL_STATE_HIGHWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 38, "x": 270, "y": 244 }, "POL_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "POL_NATIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "POL_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "POL_NATIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "POL_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "POL_NATIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "POL_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "POL_NATIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "POL_NATIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "POL_NATIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "POL_NATIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "POL_NATIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "POL_NATIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "POL_NATIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "POL_NATIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "POL_NATIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "POL_VOIVODESHIP-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1515, "y": 678 }, "POL_VOIVODESHIP-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 623, "y": 486 }, "POL_VOIVODESHIP-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 908, "y": 710 }, "POL_VOIVODESHIP-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 645, "y": 486 }, "POL_VOIVODESHIP-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 928, "y": 710 }, "POL_VOIVODESHIP-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 669, "y": 486 }, "POL_VOIVODESHIP-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 956, "y": 710 }, "POL_VOIVODESHIP-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 701, "y": 486 }, "POL_VOIVODESHIP-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1146, "y": 388 }, "POL_VOIVODESHIP-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 0, "y": 518 }, "POL_VOIVODESHIP-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 992, "y": 710 }, "POL_VOIVODESHIP-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 48, "y": 518 }, "POL_VOIVODESHIP-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1041, "y": 710 }, "POL_VOIVODESHIP-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 104, "y": 518 }, "POL_VOIVODESHIP-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1098, "y": 710 }, "POL_VOIVODESHIP-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 169, "y": 518 }, "PRT_AUTO_ESTRADA_IP_IC-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "PRT_AUTO_ESTRADA_IP_IC-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "PRT_AUTO_ESTRADA_IP_IC-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "PRT_AUTO_ESTRADA_IP_IC-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "PRT_AUTO_ESTRADA_IP_IC-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "PRT_MAIN_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "PRT_MAIN_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "PRT_MAIN_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "PRT_MAIN_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "PRT_MAIN_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "PRT_MAIN_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "PRT_MAIN_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "PRT_MAIN_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "PRT_MAIN_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "PRT_MAIN_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "PRT_MAIN_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "PRT_MAIN_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "PRT_MAIN_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "PRT_MAIN_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "PRT_MAIN_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "PRT_MAIN_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "ROU_COUNTY_ROAD-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 705, "y": 388 }, "ROU_COUNTY_ROAD-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 134, "y": 94 }, "ROU_COUNTY_ROAD-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 723, "y": 388 }, "ROU_COUNTY_ROAD-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 158, "y": 94 }, "ROU_COUNTY_ROAD-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 0, "y": 422 }, "ROU_COUNTY_ROAD-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 0, "y": 134 }, "ROU_COUNTY_ROAD-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 28, "y": 422 }, "ROU_COUNTY_ROAD-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 185, "y": 0 }, "ROU_COUNTY_ROAD-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 64, "y": 422 }, "ROU_COUNTY_ROAD-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 226, "y": 0 }, "ROU_COUNTY_ROAD-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 105, "y": 422 }, "ROU_COUNTY_ROAD-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 274, "y": 0 }, "ROU_COUNTY_ROAD-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 154, "y": 422 }, "ROU_COUNTY_ROAD-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 0, "y": 172 }, "ROU_LOCAL_ROAD-1-large": { "height": 32, "pixelRatio": 1, "width": 18, "x": 750, "y": 454 }, "ROU_LOCAL_ROAD-1-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 192, "y": 134 }, "ROU_LOCAL_ROAD-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 344, "y": 550 }, "ROU_LOCAL_ROAD-2-xl": { "height": 38, "pixelRatio": 1, "width": 24, "x": 216, "y": 134 }, "ROU_LOCAL_ROAD-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 364, "y": 550 }, "ROU_LOCAL_ROAD-3-xl": { "height": 38, "pixelRatio": 1, "width": 32, "x": 240, "y": 134 }, "ROU_LOCAL_ROAD-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 392, "y": 550 }, "ROU_LOCAL_ROAD-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 308, "y": 244 }, "ROU_LOCAL_ROAD-5-large": { "height": 32, "pixelRatio": 1, "width": 41, "x": 428, "y": 550 }, "ROU_LOCAL_ROAD-5-xl": { "height": 36, "pixelRatio": 1, "width": 48, "x": 213, "y": 208 }, "ROU_LOCAL_ROAD-6-large": { "height": 32, "pixelRatio": 1, "width": 49, "x": 469, "y": 550 }, "ROU_LOCAL_ROAD-6-xl": { "height": 36, "pixelRatio": 1, "width": 56, "x": 261, "y": 208 }, "ROU_LOCAL_ROAD-7-large": { "height": 32, "pixelRatio": 1, "width": 57, "x": 518, "y": 550 }, "ROU_LOCAL_ROAD-7-xl": { "height": 36, "pixelRatio": 1, "width": 65, "x": 317, "y": 208 }, "ROU_MOTORWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "ROU_MOTORWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "ROU_MOTORWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "ROU_MOTORWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "ROU_MOTORWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "ROU_MOTORWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "ROU_MOTORWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "ROU_MOTORWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "ROU_MOTORWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "ROU_MOTORWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "ROU_MOTORWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "ROU_MOTORWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "ROU_MOTORWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "ROU_MOTORWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "ROU_MOTORWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "ROU_MOTORWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "ROU_NATIONAL_ROAD-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 311, "y": 614 }, "ROU_NATIONAL_ROAD-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 349, "y": 244 }, "ROU_NATIONAL_ROAD-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 333, "y": 614 }, "ROU_NATIONAL_ROAD-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 0, "y": 280 }, "ROU_NATIONAL_ROAD-3-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 355, "y": 614 }, "ROU_NATIONAL_ROAD-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 26, "y": 280 }, "ROU_NATIONAL_ROAD-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 385, "y": 614 }, "ROU_NATIONAL_ROAD-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 60, "y": 280 }, "RUS_FEDERAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "RUS_FEDERAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "RUS_FEDERAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "RUS_FEDERAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "RUS_FEDERAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "RUS_FEDERAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "RUS_FEDERAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "RUS_FEDERAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "RUS_FEDERAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "RUS_FEDERAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "RUS_FEDERAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "RUS_FEDERAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "RUS_FEDERAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "RUS_FEDERAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "RUS_FEDERAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "RUS_FEDERAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "SAU_NATIONAL_HIGHWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1398, "y": 518 }, "SAU_NATIONAL_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 457, "y": 352 }, "SAU_NATIONAL_HIGHWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1424, "y": 518 }, "SAU_NATIONAL_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 485, "y": 352 }, "SAU_NATIONAL_HIGHWAY_BYWAY-1-large": { "height": 24, "pixelRatio": 1, "width": 18, "x": 1032, "y": 316 }, "SAU_NATIONAL_HIGHWAY_BYWAY-1-xl": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1228, "y": 388 }, "SAU_NATIONAL_HIGHWAY_BYWAY-2-large": { "height": 24, "pixelRatio": 1, "width": 20, "x": 1050, "y": 316 }, "SAU_NATIONAL_HIGHWAY_BYWAY-2-xl": { "height": 28, "pixelRatio": 1, "width": 26, "x": 1250, "y": 388 }, "SAU_NATIONAL_HIGHWAY_BYWAY-3-large": { "height": 24, "pixelRatio": 1, "width": 28, "x": 1070, "y": 316 }, "SAU_NATIONAL_HIGHWAY_BYWAY-3-xl": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1276, "y": 388 }, "SGP_MOTORWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 904, "y": 646 }, "SGP_MOTORWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 374, "y": 388 }, "SGP_MOTORWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 922, "y": 646 }, "SGP_MOTORWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 396, "y": 388 }, "SGP_MOTORWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 942, "y": 646 }, "SGP_MOTORWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 653, "y": 550 }, "SGP_MOTORWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 970, "y": 646 }, "SGP_MOTORWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 420, "y": 388 }, "SGP_MOTORWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1006, "y": 646 }, "SGP_MOTORWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 461, "y": 388 }, "SGP_MOTORWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1047, "y": 646 }, "SGP_MOTORWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 509, "y": 388 }, "SGP_MOTORWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1096, "y": 646 }, "SGP_MOTORWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 565, "y": 388 }, "SGP_MOTORWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1153, "y": 646 }, "SGP_MOTORWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 630, "y": 388 }, "SVK_CESTY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "SVK_CESTY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "SVK_CESTY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "SVK_CESTY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "SVK_CESTY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "SVK_CESTY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "SVK_CESTY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "SVK_CESTY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "SVK_CESTY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "SVK_CESTY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "SVK_CESTY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "SVK_CESTY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "SVK_CESTY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "SVK_CESTY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "SVK_CESTY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "SVK_CESTY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "SVK_DIALNICE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1473, "y": 710 }, "SVK_DIALNICE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 661, "y": 582 }, "SVK_DIALNICE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1491, "y": 710 }, "SVK_DIALNICE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 585, "y": 518 }, "SVK_DIALNICE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 720, "y": 742 }, "SVK_DIALNICE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 683, "y": 582 }, "SVK_DIALNICE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 748, "y": 742 }, "SVK_DIALNICE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 609, "y": 518 }, "SVK_DIALNICE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1187, "y": 388 }, "SVK_DIALNICE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 263, "y": 614 }, "SVK_DIALNICE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 784, "y": 742 }, "SVK_DIALNICE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 650, "y": 518 }, "SVK_DIALNICE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 833, "y": 742 }, "SVK_DIALNICE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 0, "y": 550 }, "SVK_DIALNICE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 890, "y": 742 }, "SVK_DIALNICE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 130, "y": 550 }, "SWE_RIKSVAG-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "SWE_RIKSVAG-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "SWE_RIKSVAG-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "SWE_RIKSVAG-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "SWE_RIKSVAG-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "SWE_RIKSVAG-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "SWE_RIKSVAG-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "SWE_RIKSVAG-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "SWE_RIKSVAG-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "SWE_RIKSVAG-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "SWE_RIKSVAG-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "SWE_RIKSVAG-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "SWE_RIKSVAG-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "SWE_RIKSVAG-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "SWE_RIKSVAG-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "SWE_RIKSVAG-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "THA_MOTORWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "THA_MOTORWAY-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "THA_MOTORWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "THA_MOTORWAY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "THA_MOTORWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "THA_MOTORWAY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "THA_MOTORWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "THA_MOTORWAY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "THA_MOTORWAY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "THA_MOTORWAY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "THA_MOTORWAY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "THA_MOTORWAY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "THA_MOTORWAY-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "THA_MOTORWAY-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "THA_MOTORWAY-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "THA_MOTORWAY-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "THA_NATIONAL_ROAD-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 896, "y": 280 }, "THA_NATIONAL_ROAD-1-xl": { "height": 26, "pixelRatio": 1, "width": 24, "x": 916, "y": 280 }, "THA_NATIONAL_ROAD-2-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 940, "y": 280 }, "THA_NATIONAL_ROAD-2-xl": { "height": 26, "pixelRatio": 1, "width": 24, "x": 960, "y": 280 }, "THA_NATIONAL_ROAD-3-large": { "height": 26, "pixelRatio": 1, "width": 28, "x": 984, "y": 280 }, "THA_NATIONAL_ROAD-3-xl": { "height": 26, "pixelRatio": 1, "width": 32, "x": 1012, "y": 280 }, "THA_NATIONAL_ROAD-4-large": { "height": 26, "pixelRatio": 1, "width": 36, "x": 1044, "y": 280 }, "THA_NATIONAL_ROAD-4-xl": { "height": 26, "pixelRatio": 1, "width": 41, "x": 1080, "y": 280 }, "TUR_GOVERNMENTAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "TUR_GOVERNMENTAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "TUR_GOVERNMENTAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "TUR_GOVERNMENTAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "TUR_GOVERNMENTAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "TUR_MOTORWAY-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1450, "y": 518 }, "TUR_MOTORWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 513, "y": 352 }, "TUR_MOTORWAY-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1470, "y": 518 }, "TUR_MOTORWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 537, "y": 352 }, "TUR_MOTORWAY-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1490, "y": 518 }, "TUR_MOTORWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 561, "y": 352 }, "TUR_MOTORWAY-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 763, "y": 550 }, "TUR_MOTORWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 593, "y": 352 }, "TUR_MOTORWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 41, "x": 799, "y": 550 }, "TUR_MOTORWAY-5-xl": { "height": 34, "pixelRatio": 1, "width": 48, "x": 634, "y": 352 }, "TUR_MOTORWAY-6-large": { "height": 30, "pixelRatio": 1, "width": 49, "x": 840, "y": 550 }, "TUR_MOTORWAY-6-xl": { "height": 34, "pixelRatio": 1, "width": 56, "x": 682, "y": 352 }, "TUR_MOTORWAY-7-large": { "height": 30, "pixelRatio": 1, "width": 57, "x": 889, "y": 550 }, "TUR_MOTORWAY-7-xl": { "height": 34, "pixelRatio": 1, "width": 65, "x": 364, "y": 134 }, "TWN_EXPRESSWAY-1-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 738, "y": 352 }, "TWN_EXPRESSWAY-1-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 225, "y": 94 }, "TWN_EXPRESSWAY-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 429, "y": 134 }, "TWN_EXPRESSWAY-2-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 253, "y": 94 }, "TWN_EXPRESSWAY-3-large": { "height": 34, "pixelRatio": 1, "width": 32, "x": 451, "y": 134 }, "TWN_EXPRESSWAY-3-xl": { "height": 38, "pixelRatio": 1, "width": 38, "x": 281, "y": 94 }, "TWN_NATIONAL_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1310, "y": 388 }, "TWN_NATIONAL_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 483, "y": 134 }, "TWN_NATIONAL_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1332, "y": 388 }, "TWN_NATIONAL_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 511, "y": 134 }, "TWN_PROVINCE_ROAD-1-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 612, "y": 280 }, "TWN_PROVINCE_ROAD-1-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 272, "y": 134 }, "TWN_PROVINCE_ROAD-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 634, "y": 280 }, "TWN_PROVINCE_ROAD-2-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 300, "y": 134 }, "TWN_PROVINCE_ROAD-3-large": { "height": 34, "pixelRatio": 1, "width": 32, "x": 656, "y": 280 }, "TWN_PROVINCE_ROAD-3-xl": { "height": 38, "pixelRatio": 1, "width": 38, "x": 319, "y": 94 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1216, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 211, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1234, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 233, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1254, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 257, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1282, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 289, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1318, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 330, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1359, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 378, "y": 422 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1408, "y": 646 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 65, "y": 550 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 953, "y": 742 }, "UKR_INTERNATIONAL_NATIONAL_REGIONAL-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 434, "y": 422 }, "USA_COUNTY_HIGHWAY-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1354, "y": 388 }, "USA_COUNTY_HIGHWAY-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 539, "y": 134 }, "USA_COUNTY_HIGHWAY-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1376, "y": 388 }, "USA_COUNTY_HIGHWAY-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 567, "y": 134 }, "USA_COUNTY_HIGHWAY-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 1398, "y": 388 }, "USA_COUNTY_HIGHWAY-3-xl": { "height": 34, "pixelRatio": 1, "width": 36, "x": 595, "y": 134 }, "USA_COUNTY_HIGHWAY-4-large": { "height": 28, "pixelRatio": 1, "width": 40, "x": 1428, "y": 388 }, "USA_COUNTY_HIGHWAY-4-xl": { "height": 34, "pixelRatio": 1, "width": 47, "x": 631, "y": 134 }, "USA_COUNTY_HIGHWAY-5-large": { "height": 30, "pixelRatio": 1, "width": 47, "x": 946, "y": 550 }, "USA_COUNTY_HIGHWAY-5-xl": { "height": 34, "pixelRatio": 1, "width": 54, "x": 678, "y": 134 }, "USA_COUNTY_HIGHWAY-6-large": { "height": 30, "pixelRatio": 1, "width": 51, "x": 993, "y": 550 }, "USA_COUNTY_HIGHWAY-6-xl": { "height": 34, "pixelRatio": 1, "width": 60, "x": 383, "y": 94 }, "USA_COUNTY_HIGHWAY-7-large": { "height": 30, "pixelRatio": 1, "width": 59, "x": 1044, "y": 550 }, "USA_COUNTY_HIGHWAY-7-xl": { "height": 34, "pixelRatio": 1, "width": 69, "x": 443, "y": 94 }, "USA_DISTRICT_WASHINGTON_DC-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_DISTRICT_WASHINGTON_DC-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_DISTRICT_WASHINGTON_DC-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_DISTRICT_WASHINGTON_DC-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_HIGHWAY-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 511, "y": 614 }, "USA_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 204, "y": 280 }, "USA_HIGHWAY-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 421, "y": 614 }, "USA_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 101, "y": 280 }, "USA_HIGHWAY-3-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 443, "y": 614 }, "USA_HIGHWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 127, "y": 280 }, "USA_HIGHWAY-4-large": { "height": 32, "pixelRatio": 1, "width": 38, "x": 473, "y": 614 }, "USA_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 43, "x": 161, "y": 280 }, "USA_HIGHWAY_ALTERNATE_ROUTE-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 511, "y": 614 }, "USA_HIGHWAY_ALTERNATE_ROUTE-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 204, "y": 280 }, "USA_HIGHWAY_ALTERNATE_ROUTE-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 421, "y": 614 }, "USA_HIGHWAY_ALTERNATE_ROUTE-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 101, "y": 280 }, "USA_HIGHWAY_ALTERNATE_ROUTE-3-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 443, "y": 614 }, "USA_HIGHWAY_ALTERNATE_ROUTE-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 127, "y": 280 }, "USA_HIGHWAY_ALTERNATE_ROUTE-4-large": { "height": 32, "pixelRatio": 1, "width": 38, "x": 473, "y": 614 }, "USA_HIGHWAY_ALTERNATE_ROUTE-4-xl": { "height": 36, "pixelRatio": 1, "width": 43, "x": 161, "y": 280 }, "USA_HIGHWAY_BUSINESS_ROUTE-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 511, "y": 614 }, "USA_HIGHWAY_BUSINESS_ROUTE-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 204, "y": 280 }, "USA_HIGHWAY_BUSINESS_ROUTE-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 421, "y": 614 }, "USA_HIGHWAY_BUSINESS_ROUTE-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 101, "y": 280 }, "USA_HIGHWAY_BUSINESS_ROUTE-3-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 443, "y": 614 }, "USA_HIGHWAY_BUSINESS_ROUTE-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 127, "y": 280 }, "USA_HIGHWAY_BUSINESS_ROUTE-4-large": { "height": 32, "pixelRatio": 1, "width": 38, "x": 473, "y": 614 }, "USA_HIGHWAY_BUSINESS_ROUTE-4-xl": { "height": 36, "pixelRatio": 1, "width": 43, "x": 161, "y": 280 }, "USA_INTERSTATE_BUSINESS-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 533, "y": 614 }, "USA_INTERSTATE_BUSINESS-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 230, "y": 280 }, "USA_INTERSTATE_BUSINESS-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 555, "y": 614 }, "USA_INTERSTATE_BUSINESS-2-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 256, "y": 280 }, "USA_INTERSTATE_BUSINESS-3-large": { "height": 34, "pixelRatio": 1, "width": 30, "x": 732, "y": 134 }, "USA_INTERSTATE_BUSINESS-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 282, "y": 280 }, "USA_INTERSTATE_HIGHWAY-1-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 512, "y": 94 }, "USA_INTERSTATE_HIGHWAY-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 316, "y": 280 }, "USA_INTERSTATE_HIGHWAY-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 534, "y": 94 }, "USA_INTERSTATE_HIGHWAY-2-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 342, "y": 280 }, "USA_INTERSTATE_HIGHWAY-3-large": { "height": 34, "pixelRatio": 1, "width": 30, "x": 556, "y": 94 }, "USA_INTERSTATE_HIGHWAY-3-xl": { "height": 36, "pixelRatio": 1, "width": 34, "x": 0, "y": 316 }, "USA_INTERSTATE_HIGHWAY-4-large": { "height": 34, "pixelRatio": 1, "width": 34, "x": 586, "y": 94 }, "USA_INTERSTATE_HIGHWAY-4-xl": { "height": 36, "pixelRatio": 1, "width": 41, "x": 34, "y": 316 }, "USA_ROUTE_66-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1103, "y": 550 }, "USA_ROUTE_66-2-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 620, "y": 94 }, "USA_STATE_ALABAMA-1-large": { "height": 30, "pixelRatio": 1, "width": 16, "x": 1518, "y": 518 }, "USA_STATE_ALABAMA-1-xl": { "height": 34, "pixelRatio": 1, "width": 20, "x": 748, "y": 316 }, "USA_STATE_ALABAMA-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1125, "y": 550 }, "USA_STATE_ALABAMA-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 646, "y": 94 }, "USA_STATE_ALABAMA-3-large": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1145, "y": 550 }, "USA_STATE_ALABAMA-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 670, "y": 94 }, "USA_STATE_ALABAMA-4-large": { "height": 30, "pixelRatio": 1, "width": 36, "x": 1173, "y": 550 }, "USA_STATE_ALABAMA-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 702, "y": 94 }, "USA_STATE_ALASKA-1-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 577, "y": 614 }, "USA_STATE_ALASKA-1-xl": { "height": 34, "pixelRatio": 1, "width": 30, "x": 373, "y": 50 }, "USA_STATE_ALASKA-2-large": { "height": 32, "pixelRatio": 1, "width": 34, "x": 607, "y": 614 }, "USA_STATE_ALASKA-2-xl": { "height": 34, "pixelRatio": 1, "width": 38, "x": 403, "y": 50 }, "USA_STATE_ALASKA-3-large": { "height": 32, "pixelRatio": 1, "width": 44, "x": 641, "y": 614 }, "USA_STATE_ALASKA-3-xl": { "height": 34, "pixelRatio": 1, "width": 46, "x": 441, "y": 50 }, "USA_STATE_ALASKA-4-large": { "height": 32, "pixelRatio": 1, "width": 50, "x": 685, "y": 614 }, "USA_STATE_ALASKA-4-xl": { "height": 34, "pixelRatio": 1, "width": 55, "x": 487, "y": 50 }, "USA_STATE_ARIZONA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1468, "y": 388 }, "USA_STATE_ARIZONA-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1209, "y": 550 }, "USA_STATE_ARIZONA-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1486, "y": 388 }, "USA_STATE_ARIZONA-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1231, "y": 550 }, "USA_STATE_ARIZONA-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 751, "y": 172 }, "USA_STATE_ARIZONA-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1257, "y": 550 }, "USA_STATE_ARIZONA-4-large": { "height": 28, "pixelRatio": 1, "width": 38, "x": 781, "y": 172 }, "USA_STATE_ARIZONA-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 1291, "y": 550 }, "USA_STATE_ARKANSAS-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1334, "y": 550 }, "USA_STATE_ARKANSAS-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 735, "y": 614 }, "USA_STATE_ARKANSAS-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1356, "y": 550 }, "USA_STATE_ARKANSAS-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 0, "y": 646 }, "USA_STATE_ARKANSAS-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 1378, "y": 550 }, "USA_STATE_ARKANSAS-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 26, "y": 646 }, "USA_STATE_ARKANSAS-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1408, "y": 550 }, "USA_STATE_ARKANSAS-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 60, "y": 646 }, "USA_STATE_CALIFORNIA-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1121, "y": 280 }, "USA_STATE_CALIFORNIA-1-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1446, "y": 550 }, "USA_STATE_CALIFORNIA-2-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1141, "y": 280 }, "USA_STATE_CALIFORNIA-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1472, "y": 550 }, "USA_STATE_CALIFORNIA-3-large": { "height": 26, "pixelRatio": 1, "width": 28, "x": 1161, "y": 280 }, "USA_STATE_CALIFORNIA-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1498, "y": 550 }, "USA_STATE_CALIFORNIA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 819, "y": 172 }, "USA_STATE_CALIFORNIA-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 103, "y": 646 }, "USA_STATE_COLORADO-1-large": { "height": 24, "pixelRatio": 1, "width": 18, "x": 1098, "y": 316 }, "USA_STATE_COLORADO-1-xl": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1189, "y": 280 }, "USA_STATE_COLORADO-2-large": { "height": 24, "pixelRatio": 1, "width": 20, "x": 1116, "y": 316 }, "USA_STATE_COLORADO-2-xl": { "height": 26, "pixelRatio": 1, "width": 24, "x": 1209, "y": 280 }, "USA_STATE_COLORADO-3-large": { "height": 24, "pixelRatio": 1, "width": 28, "x": 1136, "y": 316 }, "USA_STATE_COLORADO-3-xl": { "height": 26, "pixelRatio": 1, "width": 32, "x": 1233, "y": 280 }, "USA_STATE_COLORADO-4-large": { "height": 24, "pixelRatio": 1, "width": 36, "x": 1164, "y": 316 }, "USA_STATE_COLORADO-4-xl": { "height": 26, "pixelRatio": 1, "width": 41, "x": 1265, "y": 280 }, "USA_STATE_CONNECTICUT-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_CONNECTICUT-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_CONNECTICUT-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_CONNECTICUT-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_CONNECTICUT-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_CONNECTICUT-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_CONNECTICUT-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_CONNECTICUT-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_CONNECTICUT-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_CONNECTICUT-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_CONNECTICUT-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_CONNECTICUT-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_CONNECTICUT-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_CONNECTICUT-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_CONNECTICUT-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_CONNECTICUT-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_DELAWARE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1250, "y": 172 }, "USA_STATE_DELAWARE-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 146, "y": 646 }, "USA_STATE_DELAWARE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1508, "y": 388 }, "USA_STATE_DELAWARE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 170, "y": 646 }, "USA_STATE_DELAWARE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 855, "y": 172 }, "USA_STATE_DELAWARE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 194, "y": 646 }, "USA_STATE_DELAWARE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 883, "y": 172 }, "USA_STATE_DELAWARE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 44, "y": 678 }, "USA_STATE_DELAWARE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 919, "y": 172 }, "USA_STATE_DELAWARE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 467, "y": 678 }, "USA_STATE_DELAWARE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1268, "y": 172 }, "USA_STATE_DELAWARE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 226, "y": 646 }, "USA_STATE_FLORIDA-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 960, "y": 172 }, "USA_STATE_FLORIDA-1-xl": { "height": 30, "pixelRatio": 1, "width": 24, "x": 763, "y": 582 }, "USA_STATE_FLORIDA-2-large": { "height": 28, "pixelRatio": 1, "width": 26, "x": 982, "y": 172 }, "USA_STATE_FLORIDA-2-xl": { "height": 30, "pixelRatio": 1, "width": 30, "x": 787, "y": 582 }, "USA_STATE_FLORIDA-3-large": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1008, "y": 172 }, "USA_STATE_FLORIDA-3-xl": { "height": 30, "pixelRatio": 1, "width": 38, "x": 817, "y": 582 }, "USA_STATE_FLORIDA-4-large": { "height": 28, "pixelRatio": 1, "width": 42, "x": 1042, "y": 172 }, "USA_STATE_FLORIDA-4-xl": { "height": 30, "pixelRatio": 1, "width": 47, "x": 855, "y": 582 }, "USA_STATE_GEORGIA-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 902, "y": 582 }, "USA_STATE_GEORGIA-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 282, "y": 646 }, "USA_STATE_GEORGIA-2-large": { "height": 30, "pixelRatio": 1, "width": 24, "x": 924, "y": 582 }, "USA_STATE_GEORGIA-2-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 306, "y": 646 }, "USA_STATE_GEORGIA-3-large": { "height": 30, "pixelRatio": 1, "width": 32, "x": 948, "y": 582 }, "USA_STATE_GEORGIA-3-xl": { "height": 32, "pixelRatio": 1, "width": 36, "x": 334, "y": 646 }, "USA_STATE_GEORGIA-4-large": { "height": 30, "pixelRatio": 1, "width": 40, "x": 980, "y": 582 }, "USA_STATE_GEORGIA-4-xl": { "height": 32, "pixelRatio": 1, "width": 45, "x": 370, "y": 646 }, "USA_STATE_HAWAII-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1084, "y": 172 }, "USA_STATE_HAWAII-1-xl": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1020, "y": 582 }, "USA_STATE_HAWAII-2-large": { "height": 26, "pixelRatio": 1, "width": 22, "x": 1306, "y": 280 }, "USA_STATE_HAWAII-2-xl": { "height": 30, "pixelRatio": 1, "width": 28, "x": 1048, "y": 582 }, "USA_STATE_HAWAII-3-large": { "height": 26, "pixelRatio": 1, "width": 32, "x": 1328, "y": 280 }, "USA_STATE_HAWAII-3-xl": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1076, "y": 582 }, "USA_STATE_HAWAII-4-large": { "height": 28, "pixelRatio": 1, "width": 42, "x": 1106, "y": 172 }, "USA_STATE_HAWAII-4-xl": { "height": 30, "pixelRatio": 1, "width": 49, "x": 1114, "y": 582 }, "USA_STATE_IDAHO-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1148, "y": 172 }, "USA_STATE_IDAHO-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 415, "y": 646 }, "USA_STATE_IDAHO-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1166, "y": 172 }, "USA_STATE_IDAHO-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 437, "y": 646 }, "USA_STATE_IDAHO-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1186, "y": 172 }, "USA_STATE_IDAHO-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 461, "y": 646 }, "USA_STATE_IDAHO-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1214, "y": 172 }, "USA_STATE_IDAHO-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 493, "y": 646 }, "USA_STATE_ILLINOIS-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_ILLINOIS-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_ILLINOIS-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_ILLINOIS-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_ILLINOIS-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_ILLINOIS-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_ILLINOIS-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_ILLINOIS-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_ILLINOIS-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_ILLINOIS-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_ILLINOIS-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_ILLINOIS-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_ILLINOIS-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_ILLINOIS-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_ILLINOIS-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_ILLINOIS-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_INDIANA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_INDIANA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_INDIANA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_INDIANA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_INDIANA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_INDIANA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_INDIANA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_INDIANA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_INDIANA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_INDIANA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_INDIANA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_INDIANA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_INDIANA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_INDIANA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_INDIANA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_INDIANA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_IOWA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1250, "y": 172 }, "USA_STATE_IOWA-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 146, "y": 646 }, "USA_STATE_IOWA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1508, "y": 388 }, "USA_STATE_IOWA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 170, "y": 646 }, "USA_STATE_IOWA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 855, "y": 172 }, "USA_STATE_IOWA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 194, "y": 646 }, "USA_STATE_IOWA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 883, "y": 172 }, "USA_STATE_IOWA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 44, "y": 678 }, "USA_STATE_IOWA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 919, "y": 172 }, "USA_STATE_IOWA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 467, "y": 678 }, "USA_STATE_IOWA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1268, "y": 172 }, "USA_STATE_IOWA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 226, "y": 646 }, "USA_STATE_KANSAS-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1163, "y": 582 }, "USA_STATE_KANSAS-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 534, "y": 646 }, "USA_STATE_KANSAS-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1183, "y": 582 }, "USA_STATE_KANSAS-2-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 556, "y": 646 }, "USA_STATE_KANSAS-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 1205, "y": 582 }, "USA_STATE_KANSAS-3-xl": { "height": 32, "pixelRatio": 1, "width": 36, "x": 584, "y": 646 }, "USA_STATE_KANSAS-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1235, "y": 582 }, "USA_STATE_KANSAS-4-xl": { "height": 32, "pixelRatio": 1, "width": 45, "x": 620, "y": 646 }, "USA_STATE_KENTUCKY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1250, "y": 172 }, "USA_STATE_KENTUCKY-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 146, "y": 646 }, "USA_STATE_KENTUCKY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1508, "y": 388 }, "USA_STATE_KENTUCKY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 170, "y": 646 }, "USA_STATE_KENTUCKY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 855, "y": 172 }, "USA_STATE_KENTUCKY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 194, "y": 646 }, "USA_STATE_KENTUCKY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 883, "y": 172 }, "USA_STATE_KENTUCKY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 44, "y": 678 }, "USA_STATE_KENTUCKY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 919, "y": 172 }, "USA_STATE_KENTUCKY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 467, "y": 678 }, "USA_STATE_KENTUCKY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1268, "y": 172 }, "USA_STATE_KENTUCKY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 226, "y": 646 }, "USA_STATE_LOUISIANA-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1360, "y": 280 }, "USA_STATE_LOUISIANA-1-xl": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1317, "y": 172 }, "USA_STATE_LOUISIANA-2-large": { "height": 26, "pixelRatio": 1, "width": 22, "x": 1380, "y": 280 }, "USA_STATE_LOUISIANA-2-xl": { "height": 28, "pixelRatio": 1, "width": 26, "x": 1339, "y": 172 }, "USA_STATE_LOUISIANA-3-large": { "height": 26, "pixelRatio": 1, "width": 30, "x": 1402, "y": 280 }, "USA_STATE_LOUISIANA-3-xl": { "height": 28, "pixelRatio": 1, "width": 34, "x": 1365, "y": 172 }, "USA_STATE_LOUISIANA-4-large": { "height": 26, "pixelRatio": 1, "width": 38, "x": 1432, "y": 280 }, "USA_STATE_LOUISIANA-4-xl": { "height": 28, "pixelRatio": 1, "width": 43, "x": 1399, "y": 172 }, "USA_STATE_MAINE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_MAINE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_MAINE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_MAINE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_MAINE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_MAINE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_MAINE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_MAINE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_MAINE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_MAINE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_MAINE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_MAINE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_MAINE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_MAINE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_MAINE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_MAINE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_MARYLAND-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_MARYLAND-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_MARYLAND-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_MARYLAND-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_MARYLAND-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_MARYLAND-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_MARYLAND-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_MARYLAND-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_MARYLAND-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_MARYLAND-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_MARYLAND-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_MARYLAND-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_MARYLAND-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_MARYLAND-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_MARYLAND-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_MARYLAND-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_MASSACHUSETTS-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_MASSACHUSETTS-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_MASSACHUSETTS-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_MASSACHUSETTS-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_MASSACHUSETTS-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_MASSACHUSETTS-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_MASSACHUSETTS-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_MASSACHUSETTS-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_MASSACHUSETTS-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_MASSACHUSETTS-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_MASSACHUSETTS-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_MASSACHUSETTS-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_MASSACHUSETTS-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_MASSACHUSETTS-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_MASSACHUSETTS-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_MASSACHUSETTS-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_MICHIGAN-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 665, "y": 646 }, "USA_STATE_MICHIGAN-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 743, "y": 94 }, "USA_STATE_MICHIGAN-2-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 687, "y": 646 }, "USA_STATE_MICHIGAN-2-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 542, "y": 50 }, "USA_STATE_MICHIGAN-3-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 715, "y": 646 }, "USA_STATE_MICHIGAN-3-xl": { "height": 34, "pixelRatio": 1, "width": 40, "x": 574, "y": 50 }, "USA_STATE_MICHIGAN-4-large": { "height": 32, "pixelRatio": 1, "width": 44, "x": 0, "y": 678 }, "USA_STATE_MICHIGAN-4-xl": { "height": 34, "pixelRatio": 1, "width": 49, "x": 614, "y": 50 }, "USA_STATE_MINNESOTA-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1470, "y": 280 }, "USA_STATE_MINNESOTA-1-xl": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1442, "y": 172 }, "USA_STATE_MINNESOTA-2-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1490, "y": 280 }, "USA_STATE_MINNESOTA-2-xl": { "height": 28, "pixelRatio": 1, "width": 24, "x": 1464, "y": 172 }, "USA_STATE_MINNESOTA-3-large": { "height": 26, "pixelRatio": 1, "width": 28, "x": 768, "y": 316 }, "USA_STATE_MINNESOTA-3-xl": { "height": 28, "pixelRatio": 1, "width": 32, "x": 1488, "y": 172 }, "USA_STATE_MINNESOTA-4-large": { "height": 26, "pixelRatio": 1, "width": 36, "x": 796, "y": 316 }, "USA_STATE_MINNESOTA-4-xl": { "height": 28, "pixelRatio": 1, "width": 41, "x": 762, "y": 208 }, "USA_STATE_MISSISSIPPI-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1250, "y": 172 }, "USA_STATE_MISSISSIPPI-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 146, "y": 646 }, "USA_STATE_MISSISSIPPI-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1508, "y": 388 }, "USA_STATE_MISSISSIPPI-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 170, "y": 646 }, "USA_STATE_MISSISSIPPI-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 855, "y": 172 }, "USA_STATE_MISSISSIPPI-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 194, "y": 646 }, "USA_STATE_MISSISSIPPI-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 883, "y": 172 }, "USA_STATE_MISSISSIPPI-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 44, "y": 678 }, "USA_STATE_MISSISSIPPI-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 919, "y": 172 }, "USA_STATE_MISSISSIPPI-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 467, "y": 678 }, "USA_STATE_MISSISSIPPI-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1268, "y": 172 }, "USA_STATE_MISSISSIPPI-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 226, "y": 646 }, "USA_STATE_MISSOURI-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 85, "y": 678 }, "USA_STATE_MISSOURI-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 663, "y": 50 }, "USA_STATE_MISSOURI-2-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 107, "y": 678 }, "USA_STATE_MISSOURI-2-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 687, "y": 50 }, "USA_STATE_MISSOURI-3-large": { "height": 32, "pixelRatio": 1, "width": 30, "x": 129, "y": 678 }, "USA_STATE_MISSOURI-3-xl": { "height": 34, "pixelRatio": 1, "width": 34, "x": 713, "y": 50 }, "USA_STATE_MISSOURI-4-large": { "height": 32, "pixelRatio": 1, "width": 38, "x": 159, "y": 678 }, "USA_STATE_MISSOURI-4-xl": { "height": 34, "pixelRatio": 1, "width": 43, "x": 368, "y": 0 }, "USA_STATE_MONTANA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_MONTANA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_MONTANA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_MONTANA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_MONTANA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_MONTANA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_MONTANA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_MONTANA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_MONTANA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_MONTANA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_MONTANA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_MONTANA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_MONTANA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_MONTANA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_MONTANA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_MONTANA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_NEBRASKA-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1273, "y": 582 }, "USA_STATE_NEBRASKA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 197, "y": 678 }, "USA_STATE_NEBRASKA-2-large": { "height": 30, "pixelRatio": 1, "width": 24, "x": 1293, "y": 582 }, "USA_STATE_NEBRASKA-2-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 219, "y": 678 }, "USA_STATE_NEBRASKA-3-large": { "height": 30, "pixelRatio": 1, "width": 32, "x": 1317, "y": 582 }, "USA_STATE_NEBRASKA-3-xl": { "height": 32, "pixelRatio": 1, "width": 36, "x": 247, "y": 678 }, "USA_STATE_NEBRASKA-4-large": { "height": 30, "pixelRatio": 1, "width": 40, "x": 1349, "y": 582 }, "USA_STATE_NEBRASKA-4-xl": { "height": 32, "pixelRatio": 1, "width": 45, "x": 283, "y": 678 }, "USA_STATE_NEVADA-1-large": { "height": 34, "pixelRatio": 1, "width": 18, "x": 747, "y": 50 }, "USA_STATE_NEVADA-1-xl": { "height": 36, "pixelRatio": 1, "width": 22, "x": 75, "y": 316 }, "USA_STATE_NEVADA-2-large": { "height": 34, "pixelRatio": 1, "width": 20, "x": 411, "y": 0 }, "USA_STATE_NEVADA-2-xl": { "height": 36, "pixelRatio": 1, "width": 24, "x": 97, "y": 316 }, "USA_STATE_NEVADA-3-large": { "height": 34, "pixelRatio": 1, "width": 26, "x": 431, "y": 0 }, "USA_STATE_NEVADA-3-xl": { "height": 36, "pixelRatio": 1, "width": 30, "x": 121, "y": 316 }, "USA_STATE_NEVADA-4-large": { "height": 34, "pixelRatio": 1, "width": 34, "x": 457, "y": 0 }, "USA_STATE_NEVADA-4-xl": { "height": 36, "pixelRatio": 1, "width": 39, "x": 151, "y": 316 }, "USA_STATE_NEW_HAMPSHIRE-1-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1389, "y": 582 }, "USA_STATE_NEW_HAMPSHIRE-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 328, "y": 678 }, "USA_STATE_NEW_HAMPSHIRE-2-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1411, "y": 582 }, "USA_STATE_NEW_HAMPSHIRE-2-xl": { "height": 32, "pixelRatio": 1, "width": 30, "x": 352, "y": 678 }, "USA_STATE_NEW_HAMPSHIRE-3-large": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1437, "y": 582 }, "USA_STATE_NEW_HAMPSHIRE-3-xl": { "height": 32, "pixelRatio": 1, "width": 38, "x": 382, "y": 678 }, "USA_STATE_NEW_HAMPSHIRE-4-large": { "height": 30, "pixelRatio": 1, "width": 42, "x": 1471, "y": 582 }, "USA_STATE_NEW_HAMPSHIRE-4-xl": { "height": 32, "pixelRatio": 1, "width": 47, "x": 420, "y": 678 }, "USA_STATE_NEW_JERSEY-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1250, "y": 172 }, "USA_STATE_NEW_JERSEY-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 146, "y": 646 }, "USA_STATE_NEW_JERSEY-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1508, "y": 388 }, "USA_STATE_NEW_JERSEY-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 170, "y": 646 }, "USA_STATE_NEW_JERSEY-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 855, "y": 172 }, "USA_STATE_NEW_JERSEY-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 194, "y": 646 }, "USA_STATE_NEW_JERSEY-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 883, "y": 172 }, "USA_STATE_NEW_JERSEY-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 44, "y": 678 }, "USA_STATE_NEW_JERSEY-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 919, "y": 172 }, "USA_STATE_NEW_JERSEY-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 467, "y": 678 }, "USA_STATE_NEW_JERSEY-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1268, "y": 172 }, "USA_STATE_NEW_JERSEY-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 226, "y": 646 }, "USA_STATE_NEW_MEXICO-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1513, "y": 582 }, "USA_STATE_NEW_MEXICO-1-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 515, "y": 678 }, "USA_STATE_NEW_MEXICO-2-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 759, "y": 614 }, "USA_STATE_NEW_MEXICO-2-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 539, "y": 678 }, "USA_STATE_NEW_MEXICO-3-large": { "height": 30, "pixelRatio": 1, "width": 34, "x": 785, "y": 614 }, "USA_STATE_NEW_MEXICO-3-xl": { "height": 32, "pixelRatio": 1, "width": 40, "x": 571, "y": 678 }, "USA_STATE_NEW_MEXICO-4-large": { "height": 30, "pixelRatio": 1, "width": 42, "x": 819, "y": 614 }, "USA_STATE_NEW_MEXICO-4-xl": { "height": 32, "pixelRatio": 1, "width": 49, "x": 611, "y": 678 }, "USA_STATE_NEW_YORK-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 861, "y": 614 }, "USA_STATE_NEW_YORK-1-xl": { "height": 34, "pixelRatio": 1, "width": 22, "x": 491, "y": 0 }, "USA_STATE_NEW_YORK-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 881, "y": 614 }, "USA_STATE_NEW_YORK-2-xl": { "height": 34, "pixelRatio": 1, "width": 26, "x": 513, "y": 0 }, "USA_STATE_NEW_YORK-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 903, "y": 614 }, "USA_STATE_NEW_YORK-3-xl": { "height": 34, "pixelRatio": 1, "width": 34, "x": 539, "y": 0 }, "USA_STATE_NEW_YORK-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 933, "y": 614 }, "USA_STATE_NEW_YORK-4-xl": { "height": 34, "pixelRatio": 1, "width": 43, "x": 573, "y": 0 }, "USA_STATE_NORTH_CAROLINA-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 660, "y": 678 }, "USA_STATE_NORTH_CAROLINA-1-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 616, "y": 0 }, "USA_STATE_NORTH_CAROLINA-2-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 682, "y": 678 }, "USA_STATE_NORTH_CAROLINA-2-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 640, "y": 0 }, "USA_STATE_NORTH_CAROLINA-3-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 710, "y": 678 }, "USA_STATE_NORTH_CAROLINA-3-xl": { "height": 34, "pixelRatio": 1, "width": 40, "x": 672, "y": 0 }, "USA_STATE_NORTH_CAROLINA-4-large": { "height": 32, "pixelRatio": 1, "width": 44, "x": 0, "y": 710 }, "USA_STATE_NORTH_CAROLINA-4-xl": { "height": 34, "pixelRatio": 1, "width": 49, "x": 712, "y": 0 }, "USA_STATE_NORTH_DAKOTA-1-large": { "height": 30, "pixelRatio": 1, "width": 24, "x": 971, "y": 614 }, "USA_STATE_NORTH_DAKOTA-1-xl": { "height": 32, "pixelRatio": 1, "width": 28, "x": 44, "y": 710 }, "USA_STATE_NORTH_DAKOTA-2-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 995, "y": 614 }, "USA_STATE_NORTH_DAKOTA-2-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 72, "y": 710 }, "USA_STATE_NORTH_DAKOTA-3-large": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1021, "y": 614 }, "USA_STATE_NORTH_DAKOTA-3-xl": { "height": 32, "pixelRatio": 1, "width": 40, "x": 106, "y": 710 }, "USA_STATE_NORTH_DAKOTA-4-large": { "height": 30, "pixelRatio": 1, "width": 42, "x": 1055, "y": 614 }, "USA_STATE_NORTH_DAKOTA-4-xl": { "height": 32, "pixelRatio": 1, "width": 49, "x": 146, "y": 710 }, "USA_STATE_OHIO-1-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 1097, "y": 614 }, "USA_STATE_OHIO-1-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 195, "y": 710 }, "USA_STATE_OHIO-2-large": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1117, "y": 614 }, "USA_STATE_OHIO-2-xl": { "height": 32, "pixelRatio": 1, "width": 26, "x": 221, "y": 710 }, "USA_STATE_OHIO-3-large": { "height": 30, "pixelRatio": 1, "width": 30, "x": 1139, "y": 614 }, "USA_STATE_OHIO-3-xl": { "height": 32, "pixelRatio": 1, "width": 34, "x": 247, "y": 710 }, "USA_STATE_OHIO-4-large": { "height": 30, "pixelRatio": 1, "width": 38, "x": 1169, "y": 614 }, "USA_STATE_OHIO-4-xl": { "height": 32, "pixelRatio": 1, "width": 43, "x": 281, "y": 710 }, "USA_STATE_OKLAHOMA-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 1510, "y": 280 }, "USA_STATE_OKLAHOMA-1-xl": { "height": 28, "pixelRatio": 1, "width": 26, "x": 803, "y": 208 }, "USA_STATE_OKLAHOMA-2-large": { "height": 26, "pixelRatio": 1, "width": 24, "x": 832, "y": 316 }, "USA_STATE_OKLAHOMA-2-xl": { "height": 28, "pixelRatio": 1, "width": 28, "x": 829, "y": 208 }, "USA_STATE_OKLAHOMA-3-large": { "height": 26, "pixelRatio": 1, "width": 32, "x": 856, "y": 316 }, "USA_STATE_OKLAHOMA-3-xl": { "height": 28, "pixelRatio": 1, "width": 36, "x": 857, "y": 208 }, "USA_STATE_OKLAHOMA-4-large": { "height": 26, "pixelRatio": 1, "width": 40, "x": 888, "y": 316 }, "USA_STATE_OKLAHOMA-4-xl": { "height": 28, "pixelRatio": 1, "width": 45, "x": 893, "y": 208 }, "USA_STATE_OREGON-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 746, "y": 678 }, "USA_STATE_OREGON-1-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 190, "y": 316 }, "USA_STATE_OREGON-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 0, "y": 388 }, "USA_STATE_OREGON-2-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 185, "y": 50 }, "USA_STATE_OREGON-3-large": { "height": 34, "pixelRatio": 1, "width": 32, "x": 22, "y": 388 }, "USA_STATE_OREGON-3-xl": { "height": 38, "pixelRatio": 1, "width": 38, "x": 213, "y": 50 }, "USA_STATE_OREGON-4-large": { "height": 36, "pixelRatio": 1, "width": 42, "x": 218, "y": 316 }, "USA_STATE_OREGON-4-xl": { "height": 40, "pixelRatio": 1, "width": 49, "x": 0, "y": 94 }, "USA_STATE_PENNSYLVANIA-1-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 938, "y": 208 }, "USA_STATE_PENNSYLVANIA-1-xl": { "height": 30, "pixelRatio": 1, "width": 22, "x": 1207, "y": 614 }, "USA_STATE_PENNSYLVANIA-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 958, "y": 208 }, "USA_STATE_PENNSYLVANIA-2-xl": { "height": 30, "pixelRatio": 1, "width": 26, "x": 1229, "y": 614 }, "USA_STATE_PENNSYLVANIA-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 980, "y": 208 }, "USA_STATE_PENNSYLVANIA-3-xl": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1255, "y": 614 }, "USA_STATE_PENNSYLVANIA-4-large": { "height": 28, "pixelRatio": 1, "width": 38, "x": 1010, "y": 208 }, "USA_STATE_PENNSYLVANIA-4-xl": { "height": 30, "pixelRatio": 1, "width": 43, "x": 1289, "y": 614 }, "USA_STATE_RHODE_ISLAND-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_RHODE_ISLAND-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_RHODE_ISLAND-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_RHODE_ISLAND-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_RHODE_ISLAND-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_RHODE_ISLAND-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_RHODE_ISLAND-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_RHODE_ISLAND-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_RHODE_ISLAND-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_RHODE_ISLAND-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_RHODE_ISLAND-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_RHODE_ISLAND-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_RHODE_ISLAND-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_RHODE_ISLAND-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_RHODE_ISLAND-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_RHODE_ISLAND-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_SOUTH_CAROLINA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1048, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 324, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1066, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 346, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1086, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 370, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1114, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 402, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 1150, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 443, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 1191, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 491, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1240, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 547, "y": 710 }, "USA_STATE_SOUTH_CAROLINA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1297, "y": 208 }, "USA_STATE_SOUTH_CAROLINA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 612, "y": 710 }, "USA_STATE_SOUTH_DAKOTA-1-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 687, "y": 710 }, "USA_STATE_SOUTH_DAKOTA-1-xl": { "height": 34, "pixelRatio": 1, "width": 22, "x": 54, "y": 388 }, "USA_STATE_SOUTH_DAKOTA-2-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 707, "y": 710 }, "USA_STATE_SOUTH_DAKOTA-2-xl": { "height": 34, "pixelRatio": 1, "width": 24, "x": 76, "y": 388 }, "USA_STATE_SOUTH_DAKOTA-3-large": { "height": 32, "pixelRatio": 1, "width": 28, "x": 727, "y": 710 }, "USA_STATE_SOUTH_DAKOTA-3-xl": { "height": 34, "pixelRatio": 1, "width": 32, "x": 100, "y": 388 }, "USA_STATE_SOUTH_DAKOTA-4-large": { "height": 32, "pixelRatio": 1, "width": 36, "x": 0, "y": 742 }, "USA_STATE_SOUTH_DAKOTA-4-xl": { "height": 34, "pixelRatio": 1, "width": 41, "x": 132, "y": 388 }, "USA_STATE_TENNESSEE-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_TENNESSEE-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_TENNESSEE-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_TENNESSEE-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_TENNESSEE-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_TENNESSEE-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_TENNESSEE-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_TENNESSEE-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_TENNESSEE-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_TENNESSEE-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_TENNESSEE-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_TENNESSEE-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_TENNESSEE-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_TENNESSEE-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_TENNESSEE-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_TENNESSEE-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_TEXAS-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_TEXAS-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_TEXAS-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_TEXAS-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_TEXAS-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_TEXAS-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_TEXAS-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_TEXAS-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_TEXAS-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_TEXAS-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_TEXAS-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_TEXAS-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_TEXAS-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_TEXAS-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_TEXAS-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_TEXAS-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_UTAH-1-large": { "height": 30, "pixelRatio": 1, "width": 24, "x": 1332, "y": 614 }, "USA_STATE_UTAH-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 173, "y": 388 }, "USA_STATE_UTAH-2-large": { "height": 30, "pixelRatio": 1, "width": 24, "x": 1356, "y": 614 }, "USA_STATE_UTAH-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 201, "y": 388 }, "USA_STATE_UTAH-3-large": { "height": 30, "pixelRatio": 1, "width": 34, "x": 1380, "y": 614 }, "USA_STATE_UTAH-3-xl": { "height": 34, "pixelRatio": 1, "width": 40, "x": 229, "y": 388 }, "USA_STATE_UTAH-4-large": { "height": 30, "pixelRatio": 1, "width": 44, "x": 1414, "y": 614 }, "USA_STATE_UTAH-4-xl": { "height": 34, "pixelRatio": 1, "width": 51, "x": 269, "y": 388 }, "USA_STATE_VERMONT-1-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 928, "y": 316 }, "USA_STATE_VERMONT-1-xl": { "height": 30, "pixelRatio": 1, "width": 24, "x": 1458, "y": 614 }, "USA_STATE_VERMONT-2-large": { "height": 26, "pixelRatio": 1, "width": 20, "x": 948, "y": 316 }, "USA_STATE_VERMONT-2-xl": { "height": 30, "pixelRatio": 1, "width": 24, "x": 1482, "y": 614 }, "USA_STATE_VERMONT-3-large": { "height": 26, "pixelRatio": 1, "width": 28, "x": 968, "y": 316 }, "USA_STATE_VERMONT-3-xl": { "height": 30, "pixelRatio": 1, "width": 32, "x": 751, "y": 646 }, "USA_STATE_VERMONT-4-large": { "height": 26, "pixelRatio": 1, "width": 36, "x": 996, "y": 316 }, "USA_STATE_VERMONT-4-xl": { "height": 30, "pixelRatio": 1, "width": 41, "x": 783, "y": 646 }, "USA_STATE_VIRGINIA-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 36, "y": 742 }, "USA_STATE_VIRGINIA-1-xl": { "height": 36, "pixelRatio": 1, "width": 28, "x": 260, "y": 316 }, "USA_STATE_VIRGINIA-2-large": { "height": 34, "pixelRatio": 1, "width": 22, "x": 320, "y": 388 }, "USA_STATE_VIRGINIA-2-xl": { "height": 38, "pixelRatio": 1, "width": 28, "x": 251, "y": 50 }, "USA_STATE_VIRGINIA-3-large": { "height": 34, "pixelRatio": 1, "width": 32, "x": 342, "y": 388 }, "USA_STATE_VIRGINIA-3-xl": { "height": 38, "pixelRatio": 1, "width": 38, "x": 279, "y": 50 }, "USA_STATE_VIRGINIA-4-large": { "height": 36, "pixelRatio": 1, "width": 42, "x": 288, "y": 316 }, "USA_STATE_VIRGINIA-4-xl": { "height": 40, "pixelRatio": 1, "width": 49, "x": 49, "y": 94 }, "USA_STATE_WASHINGTON-1-large": { "height": 32, "pixelRatio": 1, "width": 20, "x": 58, "y": 742 }, "USA_STATE_WASHINGTON-1-xl": { "height": 36, "pixelRatio": 1, "width": 22, "x": 330, "y": 316 }, "USA_STATE_WASHINGTON-2-large": { "height": 32, "pixelRatio": 1, "width": 26, "x": 78, "y": 742 }, "USA_STATE_WASHINGTON-2-xl": { "height": 36, "pixelRatio": 1, "width": 32, "x": 352, "y": 316 }, "USA_STATE_WASHINGTON-3-large": { "height": 32, "pixelRatio": 1, "width": 32, "x": 104, "y": 742 }, "USA_STATE_WASHINGTON-3-xl": { "height": 36, "pixelRatio": 1, "width": 38, "x": 0, "y": 352 }, "USA_STATE_WASHINGTON-4-large": { "height": 32, "pixelRatio": 1, "width": 40, "x": 136, "y": 742 }, "USA_STATE_WASHINGTON-4-xl": { "height": 36, "pixelRatio": 1, "width": 47, "x": 38, "y": 352 }, "USA_STATE_WEST_VIRGINIA-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "USA_STATE_WEST_VIRGINIA-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "USA_STATE_WEST_VIRGINIA-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "USA_STATE_WEST_VIRGINIA-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "USA_STATE_WEST_VIRGINIA-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "USA_STATE_WEST_VIRGINIA-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "USA_STATE_WEST_VIRGINIA-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "USA_STATE_WEST_VIRGINIA-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "USA_STATE_WEST_VIRGINIA-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "USA_STATE_WEST_VIRGINIA-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "USA_STATE_WEST_VIRGINIA-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "USA_STATE_WEST_VIRGINIA-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "USA_STATE_WEST_VIRGINIA-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "USA_STATE_WEST_VIRGINIA-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "USA_STATE_WEST_VIRGINIA-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "USA_STATE_WEST_VIRGINIA-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "USA_STATE_WISCONSIN-1-large": { "height": 30, "pixelRatio": 1, "width": 18, "x": 1506, "y": 614 }, "USA_STATE_WISCONSIN-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 176, "y": 742 }, "USA_STATE_WISCONSIN-2-large": { "height": 30, "pixelRatio": 1, "width": 20, "x": 824, "y": 646 }, "USA_STATE_WISCONSIN-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 198, "y": 742 }, "USA_STATE_WISCONSIN-3-large": { "height": 30, "pixelRatio": 1, "width": 26, "x": 844, "y": 646 }, "USA_STATE_WISCONSIN-3-xl": { "height": 32, "pixelRatio": 1, "width": 30, "x": 222, "y": 742 }, "USA_STATE_WISCONSIN-4-large": { "height": 30, "pixelRatio": 1, "width": 34, "x": 870, "y": 646 }, "USA_STATE_WISCONSIN-4-xl": { "height": 32, "pixelRatio": 1, "width": 39, "x": 252, "y": 742 }, "USA_STATE_WYOMING-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1360, "y": 208 }, "USA_STATE_WYOMING-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 291, "y": 742 }, "USA_STATE_WYOMING-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1378, "y": 208 }, "USA_STATE_WYOMING-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 313, "y": 742 }, "USA_STATE_WYOMING-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1398, "y": 208 }, "USA_STATE_WYOMING-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 337, "y": 742 }, "USA_STATE_WYOMING-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 1426, "y": 208 }, "USA_STATE_WYOMING-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 369, "y": 742 }, "ZAF_NATIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1354, "y": 388 }, "ZAF_NATIONAL_ROAD-1-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 539, "y": 134 }, "ZAF_NATIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 22, "x": 1376, "y": 388 }, "ZAF_NATIONAL_ROAD-2-xl": { "height": 34, "pixelRatio": 1, "width": 28, "x": 567, "y": 134 }, "ZAF_NATIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 30, "x": 1398, "y": 388 }, "ZAF_NATIONAL_ROAD-3-xl": { "height": 34, "pixelRatio": 1, "width": 36, "x": 595, "y": 134 }, "ZAF_NATIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 40, "x": 1428, "y": 388 }, "ZAF_NATIONAL_ROAD-4-xl": { "height": 34, "pixelRatio": 1, "width": 47, "x": 631, "y": 134 }, "ZAF_NATIONAL_ROAD-5-large": { "height": 30, "pixelRatio": 1, "width": 47, "x": 946, "y": 550 }, "ZAF_NATIONAL_ROAD-5-xl": { "height": 34, "pixelRatio": 1, "width": 54, "x": 678, "y": 134 }, "ZAF_NATIONAL_ROAD-6-large": { "height": 30, "pixelRatio": 1, "width": 51, "x": 993, "y": 550 }, "ZAF_NATIONAL_ROAD-6-xl": { "height": 34, "pixelRatio": 1, "width": 60, "x": 383, "y": 94 }, "ZAF_NATIONAL_ROAD-7-large": { "height": 30, "pixelRatio": 1, "width": 59, "x": 1044, "y": 550 }, "ZAF_NATIONAL_ROAD-7-xl": { "height": 34, "pixelRatio": 1, "width": 69, "x": 443, "y": 94 }, "ZAF_PROVINCIAL_ROAD-1-large": { "height": 32, "pixelRatio": 1, "width": 22, "x": 410, "y": 742 }, "ZAF_PROVINCIAL_ROAD-1-xl": { "height": 36, "pixelRatio": 1, "width": 26, "x": 85, "y": 352 }, "ZAF_PROVINCIAL_ROAD-2-large": { "height": 38, "pixelRatio": 1, "width": 28, "x": 317, "y": 50 }, "ZAF_PROVINCIAL_ROAD-2-xl": { "height": 44, "pixelRatio": 1, "width": 34, "x": 0, "y": 50 }, "ZAF_PROVINCIAL_ROAD-3-large": { "height": 42, "pixelRatio": 1, "width": 40, "x": 123, "y": 50 }, "ZAF_PROVINCIAL_ROAD-3-xl": { "height": 44, "pixelRatio": 1, "width": 48, "x": 34, "y": 50 }, "ZAF_PROVINCIAL_ROAD-4-large": { "height": 42, "pixelRatio": 1, "width": 50, "x": 79, "y": 0 }, "ZAF_PROVINCIAL_ROAD-4-xl": { "height": 44, "pixelRatio": 1, "width": 59, "x": 20, "y": 0 }, "ZAF_REGIONAL_ROAD-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1509, "y": 646 }, "ZAF_REGIONAL_ROAD-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 309, "y": 454 }, "ZAF_REGIONAL_ROAD-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 838, "y": 678 }, "ZAF_REGIONAL_ROAD-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 331, "y": 454 }, "ZAF_REGIONAL_ROAD-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 858, "y": 678 }, "ZAF_REGIONAL_ROAD-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 355, "y": 454 }, "ZAF_REGIONAL_ROAD-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 886, "y": 678 }, "ZAF_REGIONAL_ROAD-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 387, "y": 454 }, "ZAF_REGIONAL_ROAD-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 922, "y": 678 }, "ZAF_REGIONAL_ROAD-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 428, "y": 454 }, "ZAF_REGIONAL_ROAD-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 963, "y": 678 }, "ZAF_REGIONAL_ROAD-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 476, "y": 454 }, "ZAF_REGIONAL_ROAD-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 1012, "y": 678 }, "ZAF_REGIONAL_ROAD-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 532, "y": 454 }, "ZAF_REGIONAL_ROAD-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 1069, "y": 678 }, "ZAF_REGIONAL_ROAD-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 597, "y": 454 }, "airport-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 999, "y": 244 }, "airport-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1520, "y": 172 }, "bar-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1023, "y": 244 }, "bar-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1218, "y": 316 }, "cafe-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1047, "y": 244 }, "cafe-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1234, "y": 316 }, "default-1-large": { "height": 28, "pixelRatio": 1, "width": 18, "x": 1462, "y": 208 }, "default-1-xl": { "height": 32, "pixelRatio": 1, "width": 22, "x": 432, "y": 742 }, "default-2-large": { "height": 28, "pixelRatio": 1, "width": 20, "x": 1480, "y": 208 }, "default-2-xl": { "height": 32, "pixelRatio": 1, "width": 24, "x": 454, "y": 742 }, "default-3-large": { "height": 28, "pixelRatio": 1, "width": 28, "x": 1500, "y": 208 }, "default-3-xl": { "height": 32, "pixelRatio": 1, "width": 32, "x": 478, "y": 742 }, "default-4-large": { "height": 28, "pixelRatio": 1, "width": 36, "x": 753, "y": 244 }, "default-4-xl": { "height": 32, "pixelRatio": 1, "width": 41, "x": 510, "y": 742 }, "default-5-large": { "height": 28, "pixelRatio": 1, "width": 41, "x": 789, "y": 244 }, "default-5-xl": { "height": 32, "pixelRatio": 1, "width": 48, "x": 551, "y": 742 }, "default-6-large": { "height": 28, "pixelRatio": 1, "width": 49, "x": 830, "y": 244 }, "default-6-xl": { "height": 32, "pixelRatio": 1, "width": 56, "x": 599, "y": 742 }, "default-7-large": { "height": 28, "pixelRatio": 1, "width": 57, "x": 879, "y": 244 }, "default-7-xl": { "height": 32, "pixelRatio": 1, "width": 65, "x": 655, "y": 742 }, "default-8-large": { "height": 28, "pixelRatio": 1, "width": 63, "x": 936, "y": 244 }, "default-8-xl": { "height": 32, "pixelRatio": 1, "width": 75, "x": 758, "y": 422 }, "default_marker": { "height": 50, "pixelRatio": 1, "width": 20, "x": 0, "y": 0 }, "education-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1071, "y": 244 }, "education-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1250, "y": 316 }, "ferry-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1095, "y": 244 }, "ferry-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1266, "y": 316 }, "gas_station-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1119, "y": 244 }, "gas_station-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1282, "y": 316 }, "generic-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1143, "y": 244 }, "generic-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1298, "y": 316 }, "greenlight_center-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1167, "y": 244 }, "greenlight_center-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1314, "y": 316 }, "grocery-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1191, "y": 244 }, "grocery-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1330, "y": 316 }, "gym-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1215, "y": 244 }, "gym-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1346, "y": 316 }, "hotel-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1239, "y": 244 }, "hotel-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1362, "y": 316 }, "inc-road-closed-large": { "height": 39, "pixelRatio": 1, "width": 36, "x": 98, "y": 94 }, "inc-road-closed-medium": { "height": 31, "pixelRatio": 1, "width": 28, "x": 833, "y": 422 }, "inc-road-closed-small": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1263, "y": 244 }, "landmark-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1287, "y": 244 }, "landmark-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1378, "y": 316 }, "medical_center-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1311, "y": 244 }, "medical_center-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1394, "y": 316 }, "oneway-spaced-highway-large": { "height": 13, "pixelRatio": 1, "width": 15, "x": 861, "y": 352 }, "oneway-spaced-highway-small": { "height": 12, "pixelRatio": 1, "width": 16, "x": 906, "y": 352 }, "oneway-spaced-highway-xl": { "height": 15, "pixelRatio": 1, "width": 19, "x": 804, "y": 352 }, "oneway-spaced-highway-xxl": { "height": 18, "pixelRatio": 1, "width": 22, "x": 1506, "y": 316 }, "oneway-spaced-large": { "height": 13, "pixelRatio": 1, "width": 15, "x": 876, "y": 352 }, "oneway-spaced-small": { "height": 12, "pixelRatio": 1, "width": 16, "x": 922, "y": 352 }, "oneway-spaced-white-large": { "height": 13, "pixelRatio": 1, "width": 15, "x": 891, "y": 352 }, "oneway-spaced-white-small": { "height": 12, "pixelRatio": 1, "width": 16, "x": 938, "y": 352 }, "oneway-spaced-white-xl": { "height": 15, "pixelRatio": 1, "width": 19, "x": 823, "y": 352 }, "oneway-spaced-white-xxl": { "height": 18, "pixelRatio": 1, "width": 22, "x": 760, "y": 352 }, "oneway-spaced-xl": { "height": 15, "pixelRatio": 1, "width": 19, "x": 842, "y": 352 }, "oneway-spaced-xxl": { "height": 18, "pixelRatio": 1, "width": 22, "x": 782, "y": 352 }, "park-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1335, "y": 244 }, "park-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1410, "y": 316 }, "parking-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1359, "y": 244 }, "parking-small": { "height": 20, "pixelRatio": 1, "width": 18, "x": 1200, "y": 316 }, "rail-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1383, "y": 244 }, "rail-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1426, "y": 316 }, "restaurant-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1407, "y": 244 }, "restaurant-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1442, "y": 316 }, "shop-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1431, "y": 244 }, "shop-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1458, "y": 316 }, "stadium_and_arena-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1455, "y": 244 }, "stadium_and_arena-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1474, "y": 316 }, "tollgate-medium": { "height": 27, "pixelRatio": 1, "width": 24, "x": 1479, "y": 244 }, "tollgate-small": { "height": 19, "pixelRatio": 1, "width": 16, "x": 1490, "y": 316 } } ================================================ FILE: test/data/style.json ================================================ { "version": 8, "name": "uber-stylesheet", "minzoom": 0, "maxzoom": 22, "sources": { "composite": { "bounds": [ -180, -85.0511, 180, 85.0511 ], "center": [ 0, 0, 0 ], "name": "uber", "scheme": "xyz", "tilejson": "2.0.0", "tilezooms": [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ], "maxzoom": 14, "minzoom": 0, "prefetchable": true, "priority": 0, "tiles": [ "https://raw.githubusercontent.com/visgl/react-map-gl/master/test/data/tile/v1/{z}/{x}/{y}/COMPOSITE" ], "type": "vector" }, "poi": { "bounds": [ -180, -85.0511, 180, 85.0511 ], "center": [ 0, 0, 0 ], "name": "uber", "scheme": "xyz", "tilejson": "2.0.0", "tilezooms": [ 10, 11, 12, 13, 14 ], "maxzoom": 14, "minzoom": 10, "priority": 1, "tiles": [ "https://raw.githubusercontent.com/visgl/react-map-gl/master/test/data/tile/v1/{z}/{x}/{y}/POI" ], "type": "vector" } }, "sprite": "https://raw.githubusercontent.com/visgl/react-map-gl/master/test/data/sprite/tools/14/sprites", "glyphs": "https://raw.githubusercontent.com/visgl/react-map-gl/master/test/data/glyph/{fontstack}/{range}", "layers": [ { "id": "background", "type": "background", "paint": { "background-color": { "stops": [ [ 12, "#EDF0F6" ], [ 13, "#EDF0F6" ], [ 14, "#E6E9EF" ], [ 15, "#DFE2E6" ], [ 16, "#DFE2E6" ] ] }, "background-opacity": 1 } }, { "id": "parks", "type": "fill", "source": "composite", "source-layer": "polygons", "filter": [ "any", [ "in", "Place.type", "PARK_OR_OPEN_SPACE", "GOLF_COURSE" ], [ "in", "PlaceFeature.categoryName", "PARK", "GOLF" ], [ "in", "PlaceAreaFeature.categoryName", "PARK", "GOLF" ] ], "minzoom": 1, "paint": { "fill-color": { "stops": [ [ 5, "#DAEADB" ], [ 12, "#BDE5C1" ], [ 13, "#BDE5C1" ], [ 14, "#BDE5C1" ], [ 15, "#A7DFB6" ], [ 16, "#A7DFB6" ] ] }, "fill-opacity": 1 } }, { "id": "place-airport", "type": "fill", "source": "composite", "source-layer": "polygons", "filter": [ "any", [ "in", "Place.type", "AIRPORT" ], [ "in", "PlaceFeature.categoryName", "AIRPORT" ], [ "in", "PlaceAreaFeature.categoryName", "AIRPORT" ] ], "minzoom": 7, "paint": { "fill-color": { "stops": [ [ 12, "#d8dbe7" ], [ 13, "#d1d4e0" ], [ 14, "#c5c8d4" ], [ 15, "#c0c3cf" ] ] }, "fill-opacity": 1 } }, { "id": "place-airport-runways", "type": "fill", "source": "composite", "source-layer": "polygons", "filter": [ "any", [ "in", "Place.type", "AIRPORT_RUNWAY" ], [ "in", "PlaceFeature.categoryName", "AIRPORT_RUNWAY" ], [ "in", "PlaceAreaFeature.categoryName", "AIRPORT_RUNWAY" ] ], "minzoom": 11, "paint": { "fill-color": { "stops": [ [ 11, "#d8dbe7" ], [ 13, "#c3c6d4" ], [ 15, "#aaaebd" ] ] }, "fill-opacity": 1 } }, { "id": "stream-intermittent-minor-CASING", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "DisplayNaturalFeature.type", "INTERMITTENT_STREAM" ], [ "in", "DisplayNaturalFeature.priority", "MEDIUM", "LOW" ] ], "minzoom": 15, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#9CCEFF", "line-width": { "stops": [ [ 15, 0.5 ], [ 17, 2 ] ] }, "line-opacity": 1 } }, { "id": "stream-intermittent-major-CASING", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "DisplayNaturalFeature.type", "INTERMITTENT_STREAM" ], [ "in", "DisplayNaturalFeature.priority", "VERY_HIGH", "HIGH" ] ], "minzoom": 13, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#9CCEFF", "line-width": { "stops": [ [ 14, 2 ], [ 17, 4 ] ] }, "line-opacity": 1 } }, { "id": "stream-minor-CASING", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "DisplayNaturalFeature.type", "STREAM" ], [ "in", "DisplayNaturalFeature.priority", "MEDIUM", "LOW" ] ], "minzoom": 15, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#9CCEFF", "line-width": { "stops": [ [ 15, 0.5 ], [ 17, 2 ] ] }, "line-opacity": 1 } }, { "id": "stream-major-CASING", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "DisplayNaturalFeature.type", "STREAM" ], [ "in", "DisplayNaturalFeature.priority", "VERY_HIGH", "HIGH" ] ], "minzoom": 11, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#9CCEFF", "line-width": { "stops": [ [ 14, 2 ], [ 17, 7 ] ] }, "line-opacity": 1 } }, { "id": "stream-intermittent-minor-FILL", "ref": "stream-intermittent-minor-CASING", "paint": { "line-color": "#ACD5FD", "line-width": { "stops": [ [ 15, 0.25 ], [ 17, 1 ] ] }, "line-opacity": 1 } }, { "id": "stream-intermittent-major-FILL", "ref": "stream-intermittent-major-CASING", "paint": { "line-color": "#ACD5FD", "line-width": { "stops": [ [ 14, 0.5 ], [ 17, 2 ] ] }, "line-opacity": 1 } }, { "id": "stream-minor-FILL", "ref": "stream-minor-CASING", "paint": { "line-color": "#ACD5FD", "line-width": { "stops": [ [ 15, 0.25 ], [ 17, 1 ] ] }, "line-opacity": 1 } }, { "id": "stream-major-FILL", "ref": "stream-major-CASING", "paint": { "line-color": "#ACD5FD", "line-width": { "stops": [ [ 14, 0.5 ], [ 17, 5 ] ] }, "line-opacity": 1 } }, { "id": "water", "type": "fill", "source": "composite", "source-layer": "polygons", "filter": [ "in", "DisplayNaturalFeature.type", "WATER" ], "paint": { "fill-color": { "stops": [ [ 0, "#ACD5FD" ], [ 12, "#B3DAFF" ] ] }, "fill-outline-color": { "stops": [ [ 0, "#A1CAF9" ], [ 12, "#9CCEFF" ], [ 16, "#9CCEFF" ] ] }, "fill-antialias": true, "fill-opacity": 1 } }, { "id": "ferry", "type": "line", "source": "composite", "source-layer": "lines", "minzoom": 9, "filter": [ "all", [ "==", "Segment.type", "FERRY" ] ], "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 0, "#A1CAF9" ], [ 12, "#9CCEFF" ] ] }, "line-width": { "stops": [ [ 8.9, 0 ], [ 9, 0.25 ], [ 10, 0.25 ], [ 11, 0.5 ], [ 12, 1 ], [ 13, 1 ], [ 15.5, 2 ] ] }, "line-opacity": 1 } }, { "id": "road-tunnel-minor-arterial-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_ARTERY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 8, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 10, "#cccbca" ], [ 10.9, "#cccbca" ], [ 11, "#cccbca" ], [ 14, "#cccbca" ], [ 16, "#cccbca" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 13, 1.5 ], [ 13.8, 3.5 ], [ 14, 4 ], [ 15, 8 ], [ 16, 12 ], [ 17, 28 ], [ 18, 36 ], [ 20, 66 ] ] }, "line-opacity": 0 } }, { "id": "road-tunnel-major-arterial-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MAJOR_ARTERY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 14, "#cccbca" ], [ 16, "#cccbca" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 34 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-tunnel-minor-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_HIGHWAY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 7, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#cccbca", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-path-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "any", [ "in", "Segment.roadUsage", "WALKWAY", "STAIRS" ] ], "minzoom": 15, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 15, "#cccbca" ], [ 17, "#cccbca" ] ] }, "line-width": { "stops": [ [ 15, 4 ], [ 17, 5 ], [ 20, 26 ] ] }, "line-opacity": 0 } }, { "id": "road-parking-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadUsage", "PARKING_ROAD" ] ], "minzoom": 14, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#cccbca", "line-opacity": 0 } }, { "id": "road-local-minor-importance-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "LOCAL_ROAD_MINOR_IMPORTANCE" ], [ "!in", "Segment.roadUsage", "WALKWAY" ], [ "!in", "Segment.roadUsage", "STAIRS" ], [ "!in", "Segment.roadUsage", "PARKING_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 12, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 13, "#e4e5eb" ], [ 14, "#dcdee3" ], [ 15, "#dcdee3" ], [ 16, "#d0d1d6" ] ] }, "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 0 ], [ 14.2, 1.5 ], [ 14.3, 2.5 ], [ 15, 4 ], [ 16, 7 ], [ 17, 14 ], [ 18, 26 ], [ 20, 47 ] ] }, "line-opacity": 0 } }, { "id": "road-local-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "LOCAL_ROAD" ], [ "!in", "Segment.roadUsage", "WALKWAY" ], [ "!in", "Segment.roadUsage", "STAIRS" ], [ "!in", "Segment.roadUsage", "PARKING_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 11, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 13, "#e4e5eb" ], [ 14, "#dcdee3" ], [ 15, "#dcdee3" ], [ 16, "#d0d1d6" ] ] }, "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 0 ], [ 14.2, 1.5 ], [ 14.3, 2.5 ], [ 15, 6 ], [ 16, 12 ], [ 17, 22 ], [ 18, 26 ], [ 20, 54 ] ] }, "line-opacity": 1 } }, { "id": "road-minor-arterial-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_ARTERY" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 10, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 13, "#e4e5eb" ], [ 14, "#dcdee3" ], [ 15, "#dcdee3" ], [ 16, "#d0d1d6" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 2 ], [ 14.3, 4 ], [ 15, 8 ], [ 16, 12 ], [ 17, 28 ], [ 18, 36 ], [ 20, 66 ] ] }, "line-opacity": 1 } }, { "id": "road-major-arterial-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MAJOR_ARTERY" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 13, "#e4e5eb" ], [ 14, "#dcdee3" ], [ 15, "#dcdee3" ], [ 16, "#d0d1d6" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 32 ], [ 18, 40 ], [ 20, 66 ] ] }, "line-opacity": 1 } }, { "id": "road-minor-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_HIGHWAY" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 7, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 13, "#e4e5eb" ], [ 14, "#dcdee3" ], [ 15, "#dcdee3" ], [ 16, "#d0d1d6" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-ramp-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#919EBF", "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 2 ], [ 14.2, 3 ], [ 14.3, 4 ], [ 15, 5 ], [ 16, 12 ], [ 17, 30 ], [ 18, 40 ], [ 20, 66 ] ] } } }, { "id": "road-ramp-highway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7EC7B3", "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 2 ], [ 14.2, 3 ], [ 14.3, 4 ], [ 15, 5 ], [ 16, 12 ], [ 17, 30 ], [ 18, 40 ], [ 20, 66 ] ] } } }, { "id": "road-ramp-motorway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7E95E8", "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 2 ], [ 14.2, 3 ], [ 14.3, 4 ], [ 15, 5 ], [ 16, 12 ], [ 17, 30 ], [ 18, 40 ], [ 20, 66 ] ] } } }, { "id": "road-ramp-motorway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 9, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#919EBF", "line-width": { "stops": [ [ 12.95, 0 ], [ 14, 2 ], [ 14.2, 3 ], [ 14.3, 4 ], [ 15, 5 ], [ 16, 12 ], [ 17, 30 ], [ 18, 40 ], [ 20, 66 ] ] } } }, { "id": "road-tunnel-UNcontrolled-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!=", "Segment.controlledAccessRoad", true ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 6, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#cccbca", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-UNcontrolled-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.controlledAccessRoad", true ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 5, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#919EBF", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-tunnel-controlled-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "in", "Segment.controlledAccessRoad", true ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 6, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#67819E", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-tunnel-highway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 6, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7EC7B3", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-controlled-highway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "in", "Segment.controlledAccessRoad", true ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 5, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#5f7d8e", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-highway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 5, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7EC7B3", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 17 ], [ 17, 37 ], [ 18, 42 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-tunnel-motorway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 5, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#67819E", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 10 ], [ 16, 20 ], [ 17, 40 ], [ 18, 45 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-tunnel-motorway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "==", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 5, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7E95E8", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 10 ], [ 16, 20 ], [ 17, 40 ], [ 18, 45 ], [ 20, 62 ] ] }, "line-opacity": 0 } }, { "id": "road-motorway-CASING", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 4, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#67819E", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 10 ], [ 16, 20 ], [ 17, 40 ], [ 18, 45 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-motorway-CASING-GB-IE", "type": "line", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 4, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": "#7E95E8", "line-width": { "stops": [ [ 6, 0 ], [ 14, 0 ], [ 14.2, 4 ], [ 14.3, 5 ], [ 15, 8 ], [ 16, 20 ], [ 17, 40 ], [ 18, 45 ], [ 20, 62 ] ] }, "line-opacity": 1 } }, { "id": "road-tunnel-minor-arterial-FILL", "ref": "road-tunnel-minor-arterial-CASING", "paint": { "line-color": { "stops": [ [ 10, "#dcdde3" ], [ 10.9, "#dcdde3" ], [ 11, "#d0d2d6" ], [ 14, "#d0d2d6" ], [ 16, "#bababf" ] ] }, "line-width": { "stops": [ [ 10.95, 0.5 ], [ 11, 1 ], [ 12.5, 1 ], [ 13, 1.5 ], [ 14, 3 ], [ 15, 6 ], [ 16, 10 ], [ 17, 26 ], [ 18, 34 ], [ 20, 64 ] ] }, "line-opacity": 0.8 } }, { "id": "road-tunnel-major-arterial-FILL", "ref": "road-tunnel-major-arterial-CASING", "paint": { "line-color": { "stops": [ [ 14, "#d0d2d6" ], [ 16, "#bababf" ] ] }, "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 32 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": 0.8 } }, { "id": "road-tunnel-minor-highway-FILL", "ref": "road-tunnel-minor-highway-CASING", "paint": { "line-color": { "stops": [ [ 14, "#d0d2d6" ], [ 16, "#bababf" ] ] }, "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": 0.8 } }, { "id": "road-path-FILL", "ref": "road-path-CASING", "paint": { "line-color": { "stops": [ [ 15, "#d1d3de" ], [ 16, "#b1b4bd" ] ] }, "line-width": { "stops": [ [ 15, 2 ], [ 17, 3 ], [ 20, 24 ] ] }, "line-opacity": 1 } }, { "id": "road-parking-FILL", "ref": "road-parking-CASING", "paint": { "line-color": "#EDEDED", "line-width": { "stops": [ [ 14, 1 ], [ 15, 3 ], [ 16, 4 ], [ 17, 8 ], [ 18, 18 ], [ 20, 40 ] ] }, "line-opacity": 1 } }, { "id": "railway-line", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "==", "Segment.type", "RAILWAY" ] ], "minzoom": 14, "layout": { "line-cap": "round", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 14, "#d7dae0" ], [ 15, "#b9bfc9" ] ] }, "line-width": { "stops": [ [ 14, 1 ], [ 15, 2 ], [ 16, 5 ], [ 17, 6 ], [ 18, 7 ], [ 22, 25 ] ] }, "line-opacity": 1 } }, { "id": "railway-crosshatch", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "==", "Segment.type", "RAILWAY" ] ], "minzoom": 14, "layout": { "line-cap": "square", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 14, "#d7dae0" ], [ 15, "#b9bfc9" ] ] }, "line-dasharray": [ 0.1, 2.1, 0.1 ], "line-width": { "stops": [ [ 14, 0 ], [ 15, 6 ], [ 16, 10 ], [ 17, 12 ], [ 18, 18 ], [ 19, 20 ], [ 20, 29 ] ] }, "line-opacity": 1 } }, { "id": "road-local-minor-importance-FILL", "ref": "road-local-minor-importance-CASING", "paint": { "line-color": { "stops": [ [ 12, "#dcdde3" ], [ 12.85, "#DADAD8" ], [ 12.9, "#fafafa" ], [ 13, "#FFF" ] ] }, "line-width": { "stops": [ [ 12.95, 0.5 ], [ 13.95, 0.75 ], [ 14, 1 ], [ 15, 2 ], [ 16, 5 ], [ 17, 10 ], [ 18, 20 ], [ 20, 40 ] ] }, "line-opacity": 1 } }, { "id": "road-local-FILL", "ref": "road-local-CASING", "paint": { "line-color": { "stops": [ [ 12, "#dcdde3" ], [ 12.85, "#DADAD8" ], [ 12.9, "#fafafa" ], [ 13, "#FFF" ] ] }, "line-width": { "stops": [ [ 12.95, 0.5 ], [ 13.95, 1 ], [ 14, 1.5 ], [ 15, 4 ], [ 16, 10 ], [ 17, 20 ], [ 18, 24 ], [ 20, 52 ] ] }, "line-opacity": 1 } }, { "id": "road-oneway-arrows-minor", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "oneway", true ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD", "PARKING_ROAD", "CONNECTOR", "WALKWAY", "ROUNDABOUT" ], [ "in", "Segment.roadClass", "LOCAL_ROAD", "LOCAL_ROAD_MINOR_IMPORTANCE" ] ], "minzoom": 15, "layout": { "icon-image": { "stops": [ [ 15, "oneway-spaced-large" ], [ 16, "oneway-spaced-xl" ], [ 17, "oneway-spaced-xxl" ] ] }, "icon-padding": 2, "icon-rotation-alignment": "map", "symbol-placement": "line", "symbol-spacing": 200 }, "paint": { "icon-opacity": 1 } }, { "id": "road-oneway-arrows-minor-ROUNDABOUT", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "oneway", true ], [ "==", "Segment.roadUsage", "ROUNDABOUT" ], [ "in", "Segment.roadClass", "LOCAL_ROAD", "LOCAL_ROAD_MINOR_IMPORTANCE" ] ], "minzoom": 16, "layout": { "icon-image": { "stops": [ [ 16, "oneway-spaced-xl" ], [ 17, "oneway-spaced-xxl" ] ] }, "icon-padding": 2, "icon-rotation-alignment": "map", "symbol-placement": "line", "symbol-spacing": 200 }, "paint": { "icon-opacity": 1 } }, { "id": "road-minor-arterial-FILL", "ref": "road-minor-arterial-CASING", "paint": { "line-color": { "stops": [ [ 10, "#dcdde3" ], [ 11.85, "#DADAD8" ], [ 11.9, "#fafafa" ], [ 12, "#FFF" ] ] }, "line-width": { "stops": [ [ 10.95, 0.5 ], [ 12, 0.5 ], [ 12.5, 1 ], [ 13, 1.5 ], [ 14, 3 ], [ 15, 6 ], [ 16, 10 ], [ 17, 26 ], [ 18, 34 ], [ 20, 64 ] ] }, "line-opacity": 1 } }, { "id": "road-major-arterial-FILL", "ref": "road-major-arterial-CASING", "paint": { "line-color": "#FFF", "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 30 ], [ 18, 38 ], [ 20, 64 ] ] }, "line-opacity": 1 } }, { "id": "road-minor-highway-FILL", "ref": "road-minor-highway-CASING", "paint": { "line-color": "#FFF", "line-width": { "stops": [ [ 6, 0.3 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": 1 } }, { "id": "road-ramp-highway-FILL", "ref": "road-ramp-highway-CASING", "paint": { "line-color": { "stops": [ [ 6, "#fff" ], [ 12, "#A1AAC2" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 12, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 10 ], [ 17, 28 ], [ 18, 38 ], [ 20, 64 ] ] } } }, { "id": "road-ramp-highway-FILL-GB-IE", "ref": "road-ramp-highway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#2ab9ad" ], [ 12.5, "#2ab9ad" ], [ 14, "#2ab9ad" ], [ 14.5, "#5fc4c5" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 12, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 10 ], [ 17, 28 ], [ 18, 38 ], [ 20, 64 ] ] } } }, { "id": "road-ramp-motorway-FILL", "ref": "road-ramp-motorway-CASING", "paint": { "line-color": { "stops": [ [ 6, "#fff" ], [ 12, "#A1AAC2" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 12, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 10 ], [ 17, 28 ], [ 18, 38 ], [ 20, 64 ] ] } } }, { "id": "road-ramp-motorway-FILL-GB-IE", "ref": "road-ramp-motorway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#5473E0" ], [ 12.5, "#7E95E8" ], [ 14, "#7E95E8" ], [ 14.5, "#96AAF2" ] ] }, "line-width": { "stops": [ [ 6, 0 ], [ 12, 1.5 ], [ 14, 2 ], [ 15, 3 ], [ 16, 10 ], [ 17, 28 ], [ 18, 38 ], [ 20, 64 ] ] } } }, { "id": "road-oneway-arrows-major", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "oneway", true ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD", "CONNECTOR", "WALKWAY", "PARKING_ROAD", "ROUNDABOUT" ], [ "in", "Segment.roadClass", "MINOR_ARTERY", "MAJOR_ARTERY", "MINOR_HIGHWAY" ] ], "minzoom": 14, "layout": { "icon-image": { "stops": [ [ 14, "oneway-spaced-large" ], [ 16, "oneway-spaced-xl" ], [ 17, "oneway-spaced-xxl" ] ] }, "icon-padding": 2, "icon-rotation-alignment": "map", "symbol-placement": "line", "symbol-spacing": 200 }, "paint": { "icon-opacity": 1 } }, { "id": "road-oneway-arrows-major-ROUNDABOUT", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "oneway", true ], [ "==", "Segment.roadUsage", "ROUNDABOUT" ], [ "in", "Segment.roadClass", "MINOR_ARTERY", "MAJOR_ARTERY", "MINOR_HIGHWAY" ] ], "minzoom": 16, "layout": { "icon-image": { "stops": [ [ 16, "oneway-spaced-xl" ], [ 17, "oneway-spaced-xxl" ] ] }, "icon-padding": 2, "icon-rotation-alignment": "map", "symbol-placement": "line", "symbol-spacing": 200 }, "paint": { "icon-opacity": 1 } }, { "id": "road-tunnel-UNcontrolled-highway-FILL", "ref": "road-tunnel-UNcontrolled-highway-CASING", "paint": { "line-color": "#A1AAC2", "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 45 ], [ 20, 64 ] ] }, "line-opacity": 0.6 } }, { "id": "road-UNcontrolled-highway-FILL", "ref": "road-UNcontrolled-highway-CASING", "paint": { "line-color": { "stops": [ [ 5, "#A1AAC2" ], [ 7, "#A1AAC2" ] ] }, "line-width": { "stops": [ [ 6, 0.3 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": { "stops": [ [ 6, 0.2 ], [ 7, 1 ] ] } } }, { "id": "road-tunnel-controlled-highway-FILL", "ref": "road-tunnel-controlled-highway-CASING", "paint": { "line-color": "#7D96BD", "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": 0.6 } }, { "id": "road-tunnel-highway-FILL-GB-IE", "ref": "road-tunnel-highway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#2ab9ad" ], [ 12.5, "#2ab9ad" ], [ 14, "#2ab9ad" ], [ 14.5, "#5fc4c5" ] ] }, "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": 0.6 } }, { "id": "road-highway-FILL-GB-IE", "ref": "road-highway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#2ab9ad" ], [ 12.5, "#2ab9ad" ], [ 14, "#2ab9ad" ], [ 14.5, "#5fc4c5" ] ] }, "line-width": { "stops": [ [ 6, 0.5 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": { "stops": [ [ 6, 0.2 ], [ 7, 1 ] ] } } }, { "id": "road-controlled-highway-FILL", "ref": "road-controlled-highway-CASING", "paint": { "line-color": { "stops": [ [ 5, "#a4c5d8" ], [ 7, "#7D96BD" ] ] }, "line-width": { "stops": [ [ 6, 0.5 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 6 ], [ 16, 15 ], [ 17, 35 ], [ 18, 40 ], [ 20, 60 ] ] }, "line-opacity": { "stops": [ [ 6, 0.2 ], [ 7, 1 ] ] } } }, { "id": "road-oneway-arrows-highway", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "oneway", true ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!in", "Segment.roadUsage", "RAMP", "SLIP_ROAD" ], [ "!=", "Segment.controlledAccessRoad", true ], [ "!=", "Segment.groundLevel", "TUNNEL" ] ], "minzoom": 14, "layout": { "icon-image": { "stops": [ [ 14, "oneway-spaced-white-large" ], [ 16, "oneway-spaced-white-xl" ], [ 17, "oneway-spaced-white-xxl" ] ] }, "icon-padding": 2, "icon-rotation-alignment": "map", "symbol-placement": "line", "symbol-spacing": 200 }, "paint": { "icon-opacity": 1 } }, { "id": "road-tunnel-motorway-FILL", "ref": "road-tunnel-motorway-CASING", "paint": { "line-color": "#7D96BD", "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 8 ], [ 16, 18 ], [ 17, 38 ], [ 18, 43 ], [ 20, 60 ] ] }, "line-opacity": 0.6 } }, { "id": "road-tunnel-motorway-FILL-GB-IE", "ref": "road-tunnel-motorway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#5473E0" ], [ 12.5, "#7E95E8" ], [ 14, "#7E95E8" ], [ 14.5, "#96AAF2" ] ] }, "line-width": { "stops": [ [ 6, 1 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 8 ], [ 16, 18 ], [ 17, 38 ], [ 18, 43 ], [ 20, 60 ] ] }, "line-opacity": 0.6 } }, { "id": "road-motorway-FILL", "ref": "road-motorway-CASING", "paint": { "line-color": { "stops": [ [ 5, "#a4c5d8" ], [ 7, "#7D96BD" ] ] }, "line-width": { "stops": [ [ 4, 0.5 ], [ 6, 0.8 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 8 ], [ 16, 18 ], [ 17, 38 ], [ 18, 43 ], [ 20, 60 ] ] }, "line-opacity": { "stops": [ [ 4, 0.2 ], [ 5, 1 ] ] } } }, { "id": "road-motorway-FILL-GB-IE", "ref": "road-motorway-CASING-GB-IE", "paint": { "line-color": { "stops": [ [ 12, "#5473E0" ], [ 12.5, "#7E95E8" ], [ 14, "#7E95E8" ], [ 14.5, "#96AAF2" ] ] }, "line-width": { "stops": [ [ 4, 0.5 ], [ 6, 0.8 ], [ 8, 1 ], [ 10, 1.5 ], [ 12, 2 ], [ 13, 2 ], [ 14, 3 ], [ 15, 8 ], [ 16, 18 ], [ 17, 38 ], [ 18, 43 ], [ 20, 60 ] ] }, "line-opacity": { "stops": [ [ 4, 0 ], [ 5, 1 ] ] } } }, { "id": "state-border-minor", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "Border.adminType", "G1_COUNTRY_SUBDIVISION" ], [ "!in", "WorldFeature.iso_3166_1_a2", "AU", "BR", "CA", "CN", "IN", "MX", "RU", "US" ] ], "minzoom": 4, "layout": { "line-cap": "square", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 7, "#F2A8A4" ], [ 9, "#F5B2A7" ] ] }, "line-width": { "base": 1.3, "stops": [ [ 3, 1.2 ], [ 5, 1.7 ], [ 10, 1.7 ], [ 22, 15 ] ] }, "line-dasharray": [ 0.5, 1.5, 0.5 ], "line-opacity": { "stops": [ [ 2, 0 ], [ 2.5, 1 ], [ 15, 1 ], [ 18, 0.4 ] ] } } }, { "id": "state-border-major", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "all", [ "in", "Border.adminType", "G1_COUNTRY_SUBDIVISION" ], [ "in", "WorldFeature.iso_3166_1_a2", "AU", "BR", "CA", "CN", "IN", "MX", "RU", "US" ] ], "minzoom": 2, "layout": { "line-cap": "square", "line-join": "round" }, "paint": { "line-color": { "stops": [ [ 7, "#F2A8A4" ], [ 9, "#F5B2A7" ] ] }, "line-width": { "base": 1.3, "stops": [ [ 3, 1.2 ], [ 5, 1.7 ], [ 10, 1.7 ], [ 22, 15 ] ] }, "line-dasharray": [ 0.5, 1.5, 0.5 ], "line-opacity": { "stops": [ [ 2, 0 ], [ 2.5, 1 ], [ 15, 1 ], [ 18, 0.4 ] ] } } }, { "id": "country-border", "type": "line", "source": "composite", "source-layer": "lines", "filter": [ "in", "Border.adminType", "G0_COUNTRY" ], "layout": { "line-cap": "square", "line-join": "round" }, "paint": { "line-color": "#68696E", "line-width": { "base": 1.3, "stops": [ [ 3, 1.2 ], [ 5, 1.7 ], [ 10, 1.7 ], [ 22, 15 ] ] }, "line-dasharray": [ 0.5, 1, 0.5 ], "line-opacity": 1 } }, { "id": "road-label-minor", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "LOCAL_ROAD", "LOCAL_ROAD_MINOR_IMPORTANCE" ], [ "!in", "Segment.roadUsage", "WALKWAY" ] ], "minzoom": 14, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 13 ], [ 17, 15 ], [ 18, 17 ] ] }, "text-letter-spacing": { "stops": [ [ 14, 0.075 ], [ 15, 0.1 ], [ 16, 0.11 ], [ 17, 0.09 ], [ 18, 0.07 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 12, "#6a6c73" ], [ 13, "#5e6066" ], [ 16, "#20292E" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 16, "rgba(223, 226, 230, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-minor-arterial", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_ARTERY" ] ], "minzoom": 11, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 12 ], [ 17, 15 ], [ 18, 17 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.08 ], [ 12, 0.05 ], [ 15, 0.1 ], [ 16, 0.08 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 12, "#6a6c73" ], [ 13, "#5e6066" ], [ 16, "#20292E" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 16, "rgba(223, 226, 230, 0.5)" ], [ 16.25, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "neighborhood-label", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "any", [ "in", "Locality.type", "NEIGHBORHOOD" ], [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_12" ] ] ], "minzoom": 10, "maxzoom": 14.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11, 12 ], [ 13, 14 ] ] }, "text-padding": 1, "text-transform": "uppercase", "text-letter-spacing": 0.15, "text-max-width": 8, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 14, "#87A0D9" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 14, 1 ], [ 14.5, 0 ] ] } } }, { "id": "road-label-major-arterial", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MAJOR_ARTERY" ] ], "minzoom": 11, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.06 ], [ 12, 0.05 ], [ 15, 0.1 ], [ 16, 0.08 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 12, "#6a6c73" ], [ 13, "#5e6066" ], [ 16, "#20292E" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 16, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-minor-highway", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "Segment.roadClass", "MINOR_HIGHWAY" ] ], "minzoom": 11, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.08 ], [ 12, 0.05 ], [ 13, 0.1 ], [ 14, 0.05 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 12, "#6a6c73" ], [ 14, "#5e6066" ], [ 16, "#20292E" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 15.5, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-UNcontrolled-highway", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "!in", "Segment.controlledAccessRoad", true ] ], "minzoom": 10, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.08 ], [ 12, 0.05 ], [ 13, 0.1 ], [ 14, 0.05 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.1 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 14, "#000000" ], [ 16, "#000000" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(234, 236, 242, 0.5)" ], [ 13, "rgba(228, 229, 235, 0.5)" ], [ 14, "rgba(220, 222, 227, 0.5)" ], [ 15, "rgba(220, 222, 227, 0.5)" ], [ 16, "rgba(208, 209, 214, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-controlled-highway", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ], [ "in", "Segment.controlledAccessRoad", true ] ], "minzoom": 10, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.08 ], [ 12, 0.05 ], [ 13, 0.1 ], [ 14, 0.05 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 14, "#000000" ], [ 16, "#000000" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(234, 236, 242, 0.5)" ], [ 13, "rgba(228, 229, 235, 0.5)" ], [ 14, "rgba(220, 222, 227, 0.5)" ], [ 15, "rgba(220, 222, 227, 0.5)" ], [ 16, "rgba(208, 209, 214, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-highway-GB-IE", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "HIGHWAY" ] ], "minzoom": 10, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.08 ], [ 12, 0.05 ], [ 13, 0.1 ], [ 14, 0.05 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0.2 ] ], [ 15, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": "#475954", "text-halo-color": { "stops": [ [ 12, "rgba(234, 236, 242, 0.5)" ], [ 13, "rgba(228, 229, 235, 0.5)" ], [ 14, "rgba(220, 222, 227, 0.5)" ], [ 15, "rgba(220, 222, 227, 0.5)" ], [ 16, "rgba(208, 209, 214, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-motorway", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ] ], "minzoom": 10, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.06 ], [ 12, 0.04 ], [ 14, 0.04 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0 ] ], [ 17, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": { "stops": [ [ 14, "#000000" ], [ 16, "#000000" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(234, 236, 242, 0.5)" ], [ 13, "rgba(228, 229, 235, 0.5)" ], [ 14, "rgba(220, 222, 227, 0.5)" ], [ 15, "rgba(220, 222, 227, 0.5)" ], [ 16, "rgba(208, 209, 214, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "road-label-motorway-GB-IE", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB", "IE" ], [ "in", "Segment.roadClass", "MOTORWAY" ] ], "minzoom": 10, "layout": { "text-max-angle": 23, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 9, 14 ], [ 12, 15 ], [ 17, 17 ], [ 18, 18 ] ] }, "text-letter-spacing": { "stops": [ [ 11, 0.06 ], [ 12, 0.04 ], [ 14, 0.04 ] ] }, "text-anchor": { "stops": [ [ 14, "bottom" ], [ 15, "center" ] ] }, "text-offset": { "stops": [ [ 14, [ 0, 0 ] ], [ 17, [ 0, 0 ] ] ] }, "text-padding": 1, "text-rotation-alignment": "map", "text-field": "{name}", "symbol-placement": "line", "symbol-spacing": 300 }, "paint": { "text-color": "#2D3E7A", "text-halo-color": { "stops": [ [ 12, "rgba(234, 236, 242, 0.5)" ], [ 13, "rgba(228, 229, 235, 0.5)" ], [ 14, "rgba(220, 222, 227, 0.5)" ], [ 15, "rgba(220, 222, 227, 0.5)" ], [ 16, "rgba(208, 209, 214, 0.5)" ], [ 17, "rgba(255, 255, 255, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": 1 } }, { "id": "shield-default", "type": "symbol", "source": "composite", "source-layer": "roads", "filter": [ "all", [ "==", "shield", "default" ], [ "<=", "reflen", 8 ] ], "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "default-{reflen}-large" ], [ 12, "default-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.05 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#323232", "text-opacity": 1, "icon-opacity": 1 } }, { "id": "shield-text-color-A47D6E", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#A47D6E", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "USA_ROUTE_66" ] ] }, { "id": "shield-text-color-5676DD", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#5676DD", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "ISR_NATIONAL_ROAD", "USA_STATE_SOUTH_CAROLINA" ] ] }, { "id": "shield-text-color-ED427C", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#ED427C", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "ISR_INNER_CITY_ROAD" ] ] }, { "id": "shield-text-color-000000", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#000000", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "CAN_PROVINCIAL_NEW_BRUNSWICK_SECONDARY", "CAN_PROVINCIAL_NEW_BRUNSWICK_TERTIARY", "CAN_PROVINCIAL_NEWFOUNDLAND_AND_LABRADOR", "CAN_PROVINCIAL_NORTHWEST_TERRITORIES", "CAN_PROVINCIAL_NOVASCOTIA", "CAN_PROVINCIAL_NOVASCOTIA_SECONDARY", "CAN_PROVINCIAL_NOVASCOTIA_TERTIARY", "CAN_PROVINCIAL_YUKON" ] ] }, { "id": "shield-text-color-FFD344", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#FFD344", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "ARE_EMIRATE_HIGHWAY", "ARE_NATIONAL_HIGHWAY", "AUS_NATIONAL_HIGHWAY", "AUS_NATIONAL_HIGHWAY", "AUS_NATIONAL_HIGHWAY", "AUS_STATE_ROAD", "AUS_STATE_ROAD", "AUS_STATE_ROAD", "AUS_STATE_ROAD", "GBR_PRIMARY_ROAD", "IRL_PRIMARY_ROAD", "USA_COUNTY_HIGHWAY", "ZAF_PROVINCIAL_ROAD" ] ] }, { "id": "shield-text-color-28A084", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#28A084", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "CAN_TRANS_CANADA_HIGHWAY", "CAN_TRANS_CANADA_HIGHWAY", "ISR_REGIONAL_ROAD", "USA_STATE_VERMONT" ] ] }, { "id": "shield-text-color-515051", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#515051", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "ESP_CARRETERA_AUTONOMICA_ORANGE" ] ] }, { "id": "shield-text-color-FFFFFF", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#FFFFFF", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "ARE_OTHER_HIGHWAY", "ASIAN_HIGHWAY", "ASIAN_HIGHWAY", "ASIAN_HIGHWAY", "AUS_STATE_HIGHWAY", "AUS_TOURIST_DRIVE", "AUT_AUTOBAHN", "AUT_BUNDESSTRASSE", "AUT_SCHNELLSTRASSE", "BEL_NATIONAL_ROAD", "CAN_AUTOROUTE_QUEBEC", "CAN_PROVINCIAL_NEW_BRUNSWICK", "CAN_PROVINCIAL_QUEBEC", "CAN_PROVINCIAL_SASKATCHEWAN", "CHE_AUTOBAHN", "CHE_KANTONSSTRASSE", "CHL_FEDERAL_HIGHWAY", "CHL_STATE_HIGHWAY", "DEU_AUTOBAHN", "ESP_AUTOPISTA", "ESP_CARRETERA_AUTONOMICA_RED", "ESP_CARRETERA_RIGE", "EST_MAIN_ROAD", "EUROPEAN_ROAD", "FIN_VALTATIE", "FIN_YHDYSTIE", "FRA_AUTOROUTE", "FRA_METROPOLITAN_ROAD", "FRA_NATIONAL_ROAD", "GBR_MOTORWAY", "GRC_MOTORWAY", "GRC_NATIONAL_ROAD", "HUN_FREEWAY", "HUN_PRIMARY_SECONDARY", "IRL_MOTORWAY", "ITA_AUTOSTRADA", "ITA_STATE_HIGHWAY", "ITA_TRAFORO", "JPN_NATIONAL_ROAD", "JPN_REGIONAL_ROAD", "JPN_URBAN_EXPRESSWAY", "KOR_EXPRESS_HIGHWAY", "KOR_MOTORWAY", "KOR_NATIONAL_ROAD", "LTU_MAIN_ROAD", "MEX_MEXICO_CITY_EJE_VIAL", "MEX_MONTERREY_EJE_METROPOLITANO", "NLD_AUTOSNELWEG", "NOR_RIKSVEG", "NZL_STATE_HIGHWAY", "POL_NATIONAL_ROAD", "PRT_AUTO_ESTRADA_IP_IC", "PRT_MAIN_ROAD", "ROU_COUNTY_ROAD", "ROU_MOTORWAY", "ROU_NATIONAL_ROAD", "RUS_FEDERAL_ROAD", "SGP_MOTORWAY", "SVK_CESTY", "SVK_DIALNICE", "SWE_RIKSVAG", "THA_MOTORWAY", "TUR_GOVERNMENTAL_ROAD", "TUR_MOTORWAY", "TWN_EXPRESSWAY", "TWN_PROVINCE_ROAD", "UKR_INTERNATIONAL_NATIONAL_REGIONAL", "USA_INTERSTATE_BUSINESS", "USA_INTERSTATE_HIGHWAY", "USA_STATE_CALIFORNIA", "USA_STATE_MINNESOTA", "ZAF_NATIONAL_ROAD" ] ] }, { "id": "shield-text-color-666466", "type": "symbol", "source": "composite", "source-layer": "roads", "minzoom": 6, "layout": { "icon-image": { "stops": [ [ 9, "{shield}-{reflen}-large" ], [ 12, "{shield}-{reflen}-xl" ] ] }, "text-max-angle": 360, "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 11.99, 11 ], [ 12, 13 ] ] }, "text-letter-spacing": 0.01, "text-offset": [ 0, 0.1 ], "text-field": "{ref}", "text-rotation-alignment": "viewport", "symbol-placement": "line", "symbol-spacing": 375, "icon-rotation-alignment": "viewport", "icon-padding": 5 }, "paint": { "text-color": "#666466", "text-opacity": 1, "icon-opacity": 1 }, "filter": [ "all", [ "<=", "reflen", 8 ], [ "in", "shield", "AUS_METROPOLITAN_ROAD", "AUS_NATIONAL_HIGHWAY_ALT", "AUS_NATIONAL_ROAD", "BEL_AUTOROUTE", "BEL_RINGWEG", "BRA_FEDERAL_HIGHWAY", "BRA_STATE_HIGHWAY", "CAN_PROVINCIAL_ALBERTA", "CAN_PROVINCIAL_BRITISH_COLUMBIA", "CAN_PROVINCIAL_MANITOBA", "CAN_PROVINCIAL_PRINCE_EDWARD", "DEU_BUNDESSTRASSE", "DNK_PRIMARY_ROAD", "ESP_CARRETERA_AUTONOMICA_YELLOW", "EST_STATE_ROAD", "FIN_KANTATIE", "FRA_DEPARTMENTAL_ROAD", "IDN_NATIONAL_ROAD", "IDN_PROVINCIAL_ROAD", "IND_NATIONAL_EXPRESSWAY", "IND_NATIONAL_HIGHWAY", "IND_STATE_HIGHWAY", "LTU_STATE_ROAD", "MEX_FEDERAL_HIGHWAY", "MEX_STATE_HIGHWAY", "MYS_EXPRESSWAY", "NLD_NATIONAL_ROAD", "NLD_ONTSLUITINGS_ROAD", "NOR_RING_ROAD", "POL_VOIVODESHIP", "ROU_LOCAL_ROAD", "SAU_NATIONAL_HIGHWAY", "SAU_NATIONAL_HIGHWAY_BYWAY", "THA_NATIONAL_ROAD", "TWN_NATIONAL_HIGHWAY", "USA_DISTRICT_WASHINGTON_DC", "USA_HIGHWAY", "USA_HIGHWAY_ALTERNATE_ROUTE", "USA_HIGHWAY_BUSINESS_ROUTE", "USA_STATE_ALABAMA", "USA_STATE_ALASKA", "USA_STATE_ARIZONA", "USA_STATE_ARKANSAS", "USA_STATE_COLORADO", "USA_STATE_CONNECTICUT", "USA_STATE_DELAWARE", "USA_STATE_FLORIDA", "USA_STATE_GEORGIA", "USA_STATE_HAWAII", "USA_STATE_IDAHO", "USA_STATE_ILLINOIS", "USA_STATE_INDIANA", "USA_STATE_IOWA", "USA_STATE_KANSAS", "USA_STATE_KENTUCKY", "USA_STATE_LOUISIANA", "USA_STATE_MAINE", "USA_STATE_MARYLAND", "USA_STATE_MASSACHUSETTS", "USA_STATE_MICHIGAN", "USA_STATE_MISSISSIPPI", "USA_STATE_MISSOURI", "USA_STATE_MONTANA", "USA_STATE_NEBRASKA", "USA_STATE_NEVADA", "USA_STATE_NEW_HAMPSHIRE", "USA_STATE_NEW_JERSEY", "USA_STATE_NEW_MEXICO", "USA_STATE_NEW_YORK", "USA_STATE_NORTH_CAROLINA", "USA_STATE_NORTH_DAKOTA", "USA_STATE_OHIO", "USA_STATE_OKLAHOMA", "USA_STATE_OREGON", "USA_STATE_PENNSYLVANIA", "USA_STATE_RHODE_ISLAND", "USA_STATE_SOUTH_DAKOTA", "USA_STATE_TENNESSEE", "USA_STATE_TEXAS", "USA_STATE_UTAH", "USA_STATE_VIRGINIA", "USA_STATE_WASHINGTON", "USA_STATE_WEST_VIRGINIA", "USA_STATE_WISCONSIN", "USA_STATE_WYOMING", "ZAF_REGIONAL_ROAD" ] ] }, { "id": "poi-label-park-important", "type": "symbol", "source": "poi", "source-layer": "points2", "filter": [ "all", [ "in", "$type", "Point" ], [ "in", "PlaceFeature.categoryName", "PARK" ], [ "in", "PlaceFeature.placeDisplayPriority", "VERY_HIGH", "HIGH" ] ], "minzoom": 5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 15, 12 ], [ 16, 15 ], [ 22, 17 ] ] }, "text-justify": "center", "text-letter-spacing": 0.04, "text-anchor": "top", "text-max-width": 8, "text-padding": 4, "text-field": "{name}", "icon-image": { "stops": [ [ 12, "{icon}-small" ], [ 13, "{icon}-medium" ] ] }, "icon-padding": 4, "text-offset": { "stops": [ [ 12, [ 0, 1 ] ], [ 13, [ 0, 1.2 ] ] ] } }, "paint": { "text-color": "#118566", "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 16, "rgba(223, 226, 230, 0.5)" ], [ 17, "rgba(223, 226, 230, 0.3)" ] ] }, "text-halo-width": 2, "text-opacity": 1, "icon-opacity": 1 } }, { "id": "municipality-label-11", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_11" ] ], "minzoom": 9, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-10", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_10" ] ], "minzoom": 8.5, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-9", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_9" ] ], "minzoom": 8, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-8", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_8" ] ], "minzoom": 8, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-7", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "!in", "WorldFeature.iso_3166_1_a2", "GB" ], [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_7" ] ], "minzoom": 7, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-7-GB-TOMTOM", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "WorldFeature.iso_3166_1_a2", "GB" ], [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_7" ] ], "minzoom": 7, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 6, 11 ], [ 8, 12 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "state-label-minor", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G1_COUNTRY_SUBDIVISION" ], [ "!in", "WorldFeature.iso_3166_1_a2", "AU", "BR", "CA", "CN", "IN", "MX", "US" ] ], "minzoom": 5, "maxzoom": 8, "layout": { "visibility": "none", "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 14 ], [ 8, 18 ] ] }, "text-padding": 3, "text-transform": "uppercase", "text-max-width": 8, "text-letter-spacing": 0.4, "text-field": "{name}" }, "paint": { "text-color": "#808696", "text-halo-color": "rgba(237, 240, 246, 0.8)", "text-halo-width": 2, "text-opacity": 1 } }, { "id": "state-label-major", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G1_COUNTRY_SUBDIVISION" ], [ "in", "WorldFeature.iso_3166_1_a2", "AU", "BR", "CA", "CN", "IN", "MX", "US" ] ], "minzoom": 3, "maxzoom": 8, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 3, 12 ], [ 5, 14 ], [ 8, 18 ] ] }, "text-padding": 3, "text-transform": "uppercase", "text-max-width": 8, "text-letter-spacing": { "stops": [ [ 3, 0.2 ], [ 5, 0.2 ] ] }, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 3, "#5E6579" ], [ 5, "#808696" ] ] }, "text-halo-color": "rgba(237, 240, 246, 0.8)", "text-halo-width": 3, "text-opacity": { "stops": [ [ 3, 0 ], [ 3.3, 1 ] ] } } }, { "id": "poi-label-airport-important", "type": "symbol", "source": "poi", "source-layer": "points2", "filter": [ "all", [ "in", "$type", "Point" ], [ "in", "PlaceFeature.categoryName", "AIRPORT" ], [ "in", "PlaceFeature.placeDisplayPriority", "VERY_HIGH", "HIGH", "MEDIUM" ] ], "minzoom": 10, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 15, 12 ], [ 16, 15 ], [ 22, 17 ] ] }, "text-justify": "center", "text-letter-spacing": 0.04, "text-anchor": "top", "text-max-width": 8, "text-padding": 4, "text-field": "{name}", "icon-image": { "stops": [ [ 12, "{icon}-small" ], [ 13, "{icon}-medium" ] ] }, "icon-padding": 4, "text-offset": { "stops": [ [ 12, [ 0, 1 ] ], [ 13, [ 0, 1.2 ] ] ] } }, "paint": { "text-color": "#5B91F4", "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ], [ 15, "rgba(223, 226, 230, 0.5)" ], [ 16, "rgba(223, 226, 230, 0.5)" ], [ 17, "rgba(223, 226, 230, 0.3)" ] ] }, "text-halo-width": 2, "text-opacity": 1, "icon-opacity": 1 } }, { "id": "municipality-label-6", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_6" ] ], "minzoom": 6, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 10 ], [ 6, 12 ], [ 8, 14 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-5", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_5" ] ], "minzoom": 5.5, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 10 ], [ 6, 12 ], [ 8, 14 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-4", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_4" ] ], "minzoom": 5, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 10 ], [ 6, 12 ], [ 8, 14 ], [ 11, 14 ], [ 12, 16 ], [ 13, 19 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "country-label-4", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G0_COUNTRY" ], [ "!in", "AdminFeature.displayClass", "CLASS_1", "CLASS_2", "CLASS_3" ] ], "minzoom": 5, "maxzoom": 8, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 1, 6 ], [ 2.5, 8 ], [ 3, 12 ], [ 5, 14 ], [ 8, 20 ] ] }, "text-padding": 3, "text-transform": "none", "text-letter-spacing": { "stops": [ [ 2, 0.08 ], [ 3, 0.08 ] ] }, "text-field": "{name}", "text-max-width": 8 }, "paint": { "text-color": { "stops": [ [ 2, "#000000" ], [ 3, "#000000" ] ] }, "text-halo-color": "rgba(237, 240, 246, 0.5)", "text-halo-width": 2, "text-opacity": { "stops": [ [ 5, 1 ], [ 5.5, 0.7 ], [ 7.5, 0 ] ] } } }, { "id": "municipality-label-3", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_3" ] ], "minzoom": 5, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 12 ], [ 6, 15 ], [ 8, 16 ], [ 11, 20 ], [ 12, 23 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-2", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_2" ] ], "minzoom": 1, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 12 ], [ 6, 15 ], [ 8, 16 ], [ 11, 20 ], [ 12, 23 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 2, 0 ], [ 2.3, 1 ], [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "municipality-label-1", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "Locality.type", "CITY", "CAPITAL_CITY" ], [ "in", "Locality.displayClass", "CLASS_1" ] ], "minzoom": 1, "maxzoom": 12.5, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 5, 12 ], [ 6, 15 ], [ 8, 16 ], [ 11, 20 ], [ 12, 23 ] ] }, "text-padding": 3, "text-max-width": 8, "text-transform": "none", "text-letter-spacing": 0.07, "text-field": "{name}" }, "paint": { "text-color": { "stops": [ [ 10.5, "#585e66" ], [ 11, "#4E545B" ] ] }, "text-halo-color": { "stops": [ [ 12, "rgba(237, 240, 246, 0.5)" ], [ 13, "rgba(237, 240, 246, 0.5)" ], [ 14, "rgba(230, 233, 239, 0.5)" ] ] }, "text-halo-width": 2, "text-opacity": { "stops": [ [ 12, 1 ], [ 12.5, 0 ] ] } } }, { "id": "country-label-3", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G0_COUNTRY" ], [ "in", "AdminFeature.displayClass", "CLASS_3" ] ], "minzoom": 1, "maxzoom": 8, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 1, 10 ], [ 2.5, 12 ], [ 3, 16 ], [ 5, 18 ], [ 8, 24 ] ] }, "text-padding": 3, "text-transform": "none", "text-letter-spacing": { "stops": [ [ 2, 0.08 ], [ 3, 0.08 ] ] }, "text-field": "{name}", "text-max-width": 8 }, "paint": { "text-color": { "stops": [ [ 2, "#000000" ], [ 3, "#000000" ] ] }, "text-halo-color": "rgba(237, 240, 246, 0.5)", "text-halo-width": 2, "text-opacity": { "stops": [ [ 5, 1 ], [ 5.5, 0.7 ], [ 7.5, 0 ] ] } } }, { "id": "country-label-2", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G0_COUNTRY" ], [ "in", "AdminFeature.displayClass", "CLASS_2" ] ], "minzoom": 1, "maxzoom": 8, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 1, 10 ], [ 2.5, 12 ], [ 3, 16 ], [ 5, 18 ], [ 8, 24 ] ] }, "text-padding": 3, "text-transform": "none", "text-letter-spacing": { "stops": [ [ 2, 0.08 ], [ 3, 0.08 ] ] }, "text-field": "{name}", "text-max-width": 8 }, "paint": { "text-color": { "stops": [ [ 2, "#000000" ], [ 3, "#000000" ] ] }, "text-halo-color": "rgba(237, 240, 246, 0.5)", "text-halo-width": 2, "text-opacity": { "stops": [ [ 5, 1 ], [ 5.5, 0.7 ], [ 7.5, 0 ] ] } } }, { "id": "country-label-1", "type": "symbol", "source": "composite", "source-layer": "points", "filter": [ "all", [ "in", "AdminFeature.adminType", "G0_COUNTRY" ], [ "in", "AdminFeature.displayClass", "CLASS_1" ] ], "minzoom": 1, "maxzoom": 8, "layout": { "text-font": [ "UberMove" ], "text-size": { "stops": [ [ 1, 10 ], [ 2.5, 12 ], [ 3, 16 ], [ 5, 18 ], [ 8, 24 ] ] }, "text-padding": 3, "text-transform": "none", "text-letter-spacing": { "stops": [ [ 2, 0.08 ], [ 3, 0.08 ] ] }, "text-field": "{name}", "text-max-width": 8 }, "paint": { "text-color": { "stops": [ [ 2, "#000000" ], [ 3, "#000000" ] ] }, "text-halo-color": "rgba(237, 240, 246, 0.5)", "text-halo-width": 2, "text-opacity": { "stops": [ [ 5, 1 ], [ 5.5, 0.7 ], [ 7.5, 0 ] ] } } } ] } ================================================ FILE: test/node.js ================================================ import './src/exports'; import '../modules/main/test/utils'; import '../modules/react-mapbox/test/utils'; import '../modules/react-maplibre/test/utils'; ================================================ FILE: test/render/index.jsx ================================================ /* global window, document, FontFace */ import test from 'tape-promise/tape'; import * as React from 'react'; import {Map} from 'react-map-gl/mapbox-legacy'; import {createRoot} from 'react-dom/client'; import mapboxgl from 'mapbox-gl'; import TEST_CASES from './test-cases'; const WIDTH = 400; const HEIGHT = 300; function getBoundingBoxInPage(domElement) { const bbox = domElement.getBoundingClientRect(); return { x: window.scrollX + bbox.x, y: window.scrollY + bbox.y, width: bbox.width, height: bbox.height }; } async function runTestCase({Component = Map, props}) { const container = document.createElement('div'); container.style.width = `${WIDTH}px`; container.style.height = `${HEIGHT}px`; container.style.position = 'absolute'; container.style.zIndex = 1; document.body.append(container); return new Promise((resolve, reject) => { const root = createRoot(container); const unmount = () => { root.unmount(); container.remove(); }; const onLoad = ({target}) => { // Wait for animations to finish target.once('idle', () => { /* global setTimeout */ setTimeout( () => resolve({ map: target, boundingBox: getBoundingBoxInPage(container), unmount }), 500 ); }); }; const onError = evt => { // clean up unmount(); reject(evt.error); }; root.render(); }); } // CI does not have the same default fonts as local boxes. async function loadStyles() { const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = './node_modules/mapbox-gl/dist/mapbox-gl.css'; document.head.append(link); const font = new FontFace( 'Roboto', 'url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2)', {style: 'normal', weight: 400} ); const face = await font.load(); document.fonts.add(face); const stylesheet = document.createElement('style'); stylesheet.innerText = `.test-popup { font-family: Roboto; font-size: 20px; line-height: 1; }`; document.head.append(stylesheet); } test('Render test', async t => { // Default tape test timeout is 500ms - allow enough time for render and screenshot t.timeoutAfter(TEST_CASES.length * 4000); await loadStyles(); for (const testCase of TEST_CASES) { t.comment(testCase.title); const {threshold = 0.99, goldenImage} = testCase; let result; let error; try { const {boundingBox, unmount} = await runTestCase(testCase); result = await window.browserTestDriver_captureAndDiffScreen({ threshold, goldenImage, region: boundingBox, tolerance: 0.05, includeEmpty: false // Uncomment to save screenshot // saveOnFail: true }); error = result.error; unmount(); } catch (err) { error = err; } if (testCase.mapError) { t.ok(error, 'Map should throw error'); } else if (error) { t.fail(error.message); } else { t.ok(result && result.success, `Render test matched ${result.matchPercentage}`); } } t.end(); }); ================================================ FILE: test/render/test-cases.jsx ================================================ import * as React from 'react'; import { NavigationControl, GeolocateControl, Marker, Popup, Source, Layer } from 'react-map-gl/mapbox-legacy'; const __MAPBOX_TOKEN__ = import.meta.env.VITE_MAPBOX_TOKEN; const ALT_EMPTY_MAP_STYLE = { version: 8, sources: {}, layers: [ { id: 'background', type: 'background', paint: { 'background-color': '#F6F046', 'background-opacity': 1 } } ] }; export default [ { title: 'Basic map', props: { mapboxAccessToken: __MAPBOX_TOKEN__, mapStyle: 'mapbox://styles/mapbox/dark-v9', longitude: -122.4, latitude: 37.78, zoom: 12.5 }, threshold: 0.97, goldenImage: 'test/render/golden-images/basic-map.png' }, { title: 'Invalid map token', props: { mapboxAccessToken: 'invalid_token', mapStyle: 'mapbox://styles/mapbox/dark-v9', longitude: -122.4, latitude: 37.78, zoom: 12.5 }, mapError: true }, { title: 'Custom tile server', props: { mapboxAccessToken: __MAPBOX_TOKEN__, mapStyle: '/test/data/style.json', longitude: -122.4, latitude: 37.78, zoom: 12.5 }, threshold: 0.97, goldenImage: 'test/render/golden-images/uber-map.png' }, { title: 'NavigationControl', props: { mapboxAccessToken: __MAPBOX_TOKEN__, longitude: -122.4, latitude: 37.78, zoom: 12.5, bearing: 30, children: }, goldenImage: 'test/render/golden-images/navigation-control.png' }, { title: 'GeolocateControl', props: { mapboxAccessToken: __MAPBOX_TOKEN__, longitude: -122.4, latitude: 37.78, zoom: 12.5, bearing: 30, children: ( ) }, goldenImage: 'test/render/golden-images/geolocate-control.png' }, { title: 'Marker', props: { mapboxAccessToken: __MAPBOX_TOKEN__, longitude: -122.4, latitude: 37.78, reuseMaps: true, zoom: 12.5, children: [ , ] }, threshold: 0.95, goldenImage: 'test/render/golden-images/marker.png' }, { title: 'Popup', props: { mapboxAccessToken: __MAPBOX_TOKEN__, longitude: -122.4, latitude: 37.78, reuseMaps: true, zoom: 12.5, children: [ This is the center , Custom anchor ] }, threshold: 0.95, goldenImage: 'test/render/golden-images/popup.png' }, { title: 'JSX Source/Layer', props: { mapboxAccessToken: __MAPBOX_TOKEN__, longitude: -122.4, latitude: 37.78, zoom: 12.5, children: [ ] }, goldenImage: 'test/render/golden-images/source-01.png' }, { title: 'JSX Source/Layer toggle style', props: { mapboxAccessToken: __MAPBOX_TOKEN__, mapStyle: ALT_EMPTY_MAP_STYLE, longitude: -122.4, latitude: 37.78, zoom: 12.5, children: [ ] }, goldenImage: 'test/render/golden-images/source-02.png' }, { title: 'JSX Source/Layer removal', props: { mapboxAccessToken: __MAPBOX_TOKEN__, mapStyle: ALT_EMPTY_MAP_STYLE, longitude: -122.4, latitude: 37.78, zoom: 12.5, children: [] }, goldenImage: 'test/render/golden-images/alt-empty-map.png' } ].filter(testCase => testCase.props.mapboxAccessToken); ================================================ FILE: test/size/mapbox-legacy.js ================================================ import * as lib from 'react-map-gl/mapbox-legacy'; console.log(lib); // eslint-disable-line ================================================ FILE: test/size/mapbox.js ================================================ import * as lib from 'react-map-gl/mapbox'; console.log(lib); // eslint-disable-line ================================================ FILE: test/size/maplibre.js ================================================ import * as lib from 'react-map-gl/maplibre'; console.log(lib); // eslint-disable-line ================================================ FILE: test/src/exports.ts ================================================ import test from 'tape-promise/tape'; import * as legacyComponents from 'react-map-gl/mapbox-legacy'; import * as maplibreComponents from '@vis.gl/react-maplibre'; import * as mapboxComponents from '@vis.gl/react-mapbox'; const Components = [ 'Map', 'Source', 'Layer', 'useControl', 'useMap', 'Marker', 'Popup', 'AttributionControl', 'GeolocateControl', 'FullscreenControl', 'NavigationControl', 'ScaleControl' ] as const; function getMissingExports(module: any): null | string[] { const missingExports: string[] = []; for (const key of Components) { if (!legacyComponents[key]) { missingExports.push(key); } } return missingExports.length ? missingExports : null; } test('Consistent component names#legacy', t => { t.notOk(getMissingExports(legacyComponents), 'Legacy endpoint contains all components'); t.notOk(getMissingExports(maplibreComponents), 'Maplibre endpoint contains all components'); t.notOk(getMissingExports(mapboxComponents), 'Mapbox endpoint contains all components'); t.end(); }); ================================================ FILE: test/test-utils.js ================================================ const EPSILON = 1e-9; // Discard precision errors for comparison export function toLowPrecision(input, precision = 11) { if (Number.isFinite(input)) { return Number(input.toPrecision(precision)); } else if (Array.isArray(input)) { return input.map(item => toLowPrecision(item, precision)); } else if (input) { const output = {}; for (const key in input) { output[key] = toLowPrecision(input[key], precision); } return output; } return input; } // Compare two [lng, lat] locations, account for longitude wrapping export function isSameLocation(lngLat1, lngLat2) { const lng1 = toLowPrecision(lngLat1[0]); const lat1 = toLowPrecision(lngLat1[1]); const lng2 = toLowPrecision(lngLat2[0]); const lat2 = toLowPrecision(lngLat2[1]); return (lng1 - lng2) % 360 === 0 && lat1 === lat2; } export function equals(a, b, epsilon = EPSILON) { return Math.abs(a - b) < epsilon; } ================================================ FILE: tsconfig.json ================================================ { "ts-node": { "include": [ "modules", "test" ], // It is faster to skip typechecking. Remove if you want ts-node to do typechecking. "transpileOnly": true }, "compilerOptions": { "target": "es2020", "module": "es2020", "lib": ["DOM", "DOM.Iterable", "ES2022"], "jsx": "react", "allowJs": true, "allowSyntheticDefaultImports": true, "resolveJsonModule": true, "esModuleInterop": true, "moduleResolution": "node", "baseUrl": "./", "paths": { "react-map-gl": ["modules/main/src"], "@vis.gl/react-mapbox": ["modules/react-mapbox/src"], "@vis.gl/react-maplibre": ["modules/react-maplibre/src"] }, "plugins": [ { "transform": "@vis.gl/ts-plugins/ts-transform-append-extension", "extensions": [".js"], "after": true }, { "transform": "@vis.gl/ts-plugins/ts-transform-append-extension", "extensions": [".js"], "afterDeclarations": true } ] }, "include":[ "examples/**/*", "modules/**/*", "test/**/*" ] } ================================================ FILE: website/.eslintignore ================================================ ../dist ../examples ================================================ FILE: website/.gitignore ================================================ public/ .cache/ .docusaurus/ build/ ================================================ FILE: website/babel.config.js ================================================ module.exports = { presets: [require.resolve('@docusaurus/core/lib/babel/preset')], plugins: ["styled-components"] }; ================================================ FILE: website/docusaurus.config.js ================================================ const webpack = require('webpack'); const {getDocusaurusConfig} = require('@vis.gl/docusaurus-website'); const {resolve} = require('path'); const config = getDocusaurusConfig({ projectName: 'react-map-gl', tagline: 'React components for Mapbox GL JS and Maplibre GL JS', siteUrl: 'https://visgl.github.io/react-map-gl', repoUrl: 'https://github.com/visgl/react-map-gl', docsTableOfContents: require('../docs/table-of-contents.json'), examplesDir: './src/examples', exampleTableOfContents: require('./src/examples/table-of-contents.json'), search: 'local', webpackConfig: { plugins: [ new webpack.EnvironmentPlugin({ MapboxAccessToken: 'MapboxAccessToken' }) ], resolve: { alias: { 'mapbox-examples': resolve('../examples/mapbox'), 'maplibre-examples': resolve('../examples/maplibre') } } }, themeConfig: { footer: { copyright: '

Copyright OpenJS Foundation and vis.gl contributors. All rights reserved. The OpenJS Foundation has registered trademarks and uses trademarks. For a list of trademarks of the OpenJS Foundation, please see our Trademark Policy and Trademark List. Trademarks and logos not indicated on the list of OpenJS Foundation trademarks are trademarks™ or registered® trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.

The OpenJS Foundation | Terms of Use | Privacy Policy | Bylaws | Code of Conduct | Trademark Policy | Trademark List | Cookie Policy

' } }, customCss: [ './src/styles.css', './src/mapbox-gl.css', './src/maplibre-gl.css' ] }); module.exports = config; ================================================ FILE: website/package.json ================================================ { "name": "project-website", "version": "0.0.0", "private": true, "description": "Website for vis.gl project", "scripts": { "start": "docusaurus start", "build": "docusaurus build", "clear": "docusaurus clear", "serve": "docusaurus serve", "write-heading-ids": "ocular-doc-headers ../docs", "deploy": "docusaurus deploy" }, "resolution_notes": { "cheerio": "@cmfcmf/docusaurus-search-local breaks with v1.0.0 production release" }, "resolutions": { "cheerio": "1.0.0-rc.9" }, "dependencies": { "@docusaurus/core": "^3.0.0", "@mapbox/mapbox-gl-draw": "^1.3.0", "@mapbox/mapbox-gl-geocoder": "^4.7.4", "@maplibre/maplibre-gl-geocoder": "^1.5.0", "@vis.gl/docusaurus-website": "1.0.0-alpha.23", "@turf/area": "^6.5.0", "@turf/bbox": "^6.5.0", "d3-array": "^3.1.1", "d3-scale": "^4.0.2", "immutable": "^4.0.0", "mapbox-gl": "^3.9.0", "maplibre-gl": "^5.0.0", "react": "^18.2.0", "react-dom": "^18.2.0" }, "browserslist": [ ">0.2% and supports async-functions", "not dead" ], "volta": { "node": "18.20.5", "yarn": "1.22.22" } } ================================================ FILE: website/src/examples/index.mdx ================================================ # Examples import {ExamplesIndex} from '@vis.gl/docusaurus-website/components'; { let id = item.docId || item.label.toLowerCase(); id = id.slice(id.indexOf('/')); return `/images/examples/${id}.jpg`; }} /> ================================================ FILE: website/src/examples/mapbox/clusters.mdx ================================================ # Clusters import App from 'mapbox-examples/clusters/src/app'; ================================================ FILE: website/src/examples/mapbox/controls.mdx ================================================ # Markers, Popups and Controls import App from 'mapbox-examples/controls/src/app'; ================================================ FILE: website/src/examples/mapbox/custom-cursor.mdx ================================================ # Custom Cursor import App from 'mapbox-examples/custom-cursor/src/app'; ================================================ FILE: website/src/examples/mapbox/draggable-markers.mdx ================================================ # Draggable Marker import App from 'mapbox-examples/draggable-markers/src/app'; ================================================ FILE: website/src/examples/mapbox/draw-polygon.mdx ================================================ # Draw Polygon import App from 'mapbox-examples/draw-polygon/src/app'; ================================================ FILE: website/src/examples/mapbox/filter.mdx ================================================ # Highlight By Filter import App from 'mapbox-examples/filter/src/app'; ================================================ FILE: website/src/examples/mapbox/geocoder.mdx ================================================ # Geocoder import App from 'mapbox-examples/geocoder/src/app'; ================================================ FILE: website/src/examples/mapbox/geojson-animation.mdx ================================================ # GeoJSON Animation import App from 'mapbox-examples/geojson-animation/src/app'; ================================================ FILE: website/src/examples/mapbox/geojson.mdx ================================================ # GeoJSON import App from 'mapbox-examples/geojson/src/app'; ================================================ FILE: website/src/examples/mapbox/heatmap.mdx ================================================ # Heatmap import App from 'mapbox-examples/heatmap/src/app'; ================================================ FILE: website/src/examples/mapbox/interaction.mdx ================================================ # Limit Map Interaction import App from 'mapbox-examples/interaction/src/app'; ================================================ FILE: website/src/examples/mapbox/layers.mdx ================================================ # Dynamic Styling import App from 'mapbox-examples/layers/src/app'; ================================================ FILE: website/src/examples/mapbox/side-by-side.mdx ================================================ # Side by Side import App from 'mapbox-examples/side-by-side/src/app'; ================================================ FILE: website/src/examples/mapbox/terrain.mdx ================================================ # Terrain import App from 'mapbox-examples/terrain/src/app'; ================================================ FILE: website/src/examples/mapbox/viewport-animation.mdx ================================================ # Camera Transition import App from 'mapbox-examples/viewport-animation/src/app'; ================================================ FILE: website/src/examples/mapbox/zoom-to-bounds.mdx ================================================ # Zoom to Bounds import App from 'mapbox-examples/zoom-to-bounds/src/app'; ================================================ FILE: website/src/examples/maplibre/clusters.mdx ================================================ # Clusters import App from 'maplibre-examples/clusters/src/app'; ================================================ FILE: website/src/examples/maplibre/controls.mdx ================================================ # Markers, Popups and Controls import App from 'maplibre-examples/controls/src/app'; ================================================ FILE: website/src/examples/maplibre/custom-cursor.mdx ================================================ # Custom Cursor import App from 'maplibre-examples/custom-cursor/src/app'; ================================================ FILE: website/src/examples/maplibre/draggable-markers.mdx ================================================ # Draggable Marker import App from 'maplibre-examples/draggable-markers/src/app'; ================================================ FILE: website/src/examples/maplibre/draw-polygon.mdx ================================================ # Draw Polygon import App from 'maplibre-examples/draw-polygon/src/app'; ================================================ FILE: website/src/examples/maplibre/filter.mdx ================================================ # Highlight By Filter import App from 'maplibre-examples/filter/src/app'; ================================================ FILE: website/src/examples/maplibre/geocoder.mdx ================================================ # Geocoder import App from 'maplibre-examples/geocoder/src/app'; ================================================ FILE: website/src/examples/maplibre/geojson-animation.mdx ================================================ # GeoJSON Animation import App from 'maplibre-examples/geojson-animation/src/app'; ================================================ FILE: website/src/examples/maplibre/geojson.mdx ================================================ # GeoJSON import App from 'maplibre-examples/geojson/src/app'; ================================================ FILE: website/src/examples/maplibre/heatmap.mdx ================================================ # Heatmap import App from 'maplibre-examples/heatmap/src/app'; ================================================ FILE: website/src/examples/maplibre/interaction.mdx ================================================ # Limit Map Interaction import App from 'maplibre-examples/interaction/src/app'; ================================================ FILE: website/src/examples/maplibre/layers.mdx ================================================ # Dynamic Styling import App from 'maplibre-examples/layers/src/app'; ================================================ FILE: website/src/examples/maplibre/side-by-side.mdx ================================================ # Side by Side import App from 'maplibre-examples/side-by-side/src/app'; ================================================ FILE: website/src/examples/maplibre/terrain.mdx ================================================ # Terrain import App from 'maplibre-examples/terrain/src/app'; ================================================ FILE: website/src/examples/maplibre/viewport-animation.mdx ================================================ # Camera Transition import App from 'maplibre-examples/viewport-animation/src/app'; ================================================ FILE: website/src/examples/maplibre/zoom-to-bounds.mdx ================================================ # Zoom to Bounds import App from 'maplibre-examples/zoom-to-bounds/src/app'; ================================================ FILE: website/src/examples/table-of-contents.json ================================================ [ { "type": "doc", "label": "Overview", "id": "index" }, { "type": "category", "label": "Mapbox", "items": [ "mapbox/clusters", "mapbox/controls", "mapbox/custom-cursor", "mapbox/draggable-markers", "mapbox/draw-polygon", "mapbox/filter", "mapbox/geocoder", "mapbox/geojson-animation", "mapbox/geojson", "mapbox/heatmap", "mapbox/interaction", "mapbox/layers", "mapbox/side-by-side", "mapbox/terrain", "mapbox/viewport-animation", "mapbox/zoom-to-bounds" ] }, { "type": "category", "label": "MapLibre", "items": [ "maplibre/clusters", "maplibre/controls", "maplibre/custom-cursor", "maplibre/draggable-markers", "maplibre/draw-polygon", "maplibre/filter", "maplibre/geocoder", "maplibre/geojson-animation", "maplibre/geojson", "maplibre/heatmap", "maplibre/interaction", "maplibre/layers", "maplibre/side-by-side", "maplibre/terrain", "maplibre/viewport-animation", "maplibre/zoom-to-bounds" ] } ] ================================================ FILE: website/src/mapbox-gl.css ================================================ .mapboxgl-map{font:12px/20px Helvetica Neue,Arial,Helvetica,sans-serif;overflow:hidden;position:relative;-webkit-tap-highlight-color:rgb(0 0 0/0)}.mapboxgl-canvas{left:0;position:absolute;top:0}.mapboxgl-map:-webkit-full-screen{height:100%;width:100%}.mapboxgl-canary{background-color:salmon}.mapboxgl-canvas-container.mapboxgl-interactive,.mapboxgl-ctrl-group button.mapboxgl-ctrl-compass{cursor:grab;-webkit-user-select:none;user-select:none}.mapboxgl-canvas-container.mapboxgl-interactive.mapboxgl-track-pointer{cursor:pointer}.mapboxgl-canvas-container.mapboxgl-interactive:active,.mapboxgl-ctrl-group button.mapboxgl-ctrl-compass:active{cursor:grabbing}.mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate,.mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate .mapboxgl-canvas{touch-action:pan-x pan-y}.mapboxgl-canvas-container.mapboxgl-touch-drag-pan,.mapboxgl-canvas-container.mapboxgl-touch-drag-pan .mapboxgl-canvas{touch-action:pinch-zoom}.mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan,.mapboxgl-canvas-container.mapboxgl-touch-zoom-rotate.mapboxgl-touch-drag-pan .mapboxgl-canvas{touch-action:none}.mapboxgl-ctrl-bottom,.mapboxgl-ctrl-bottom-left,.mapboxgl-ctrl-bottom-right,.mapboxgl-ctrl-left,.mapboxgl-ctrl-right,.mapboxgl-ctrl-top,.mapboxgl-ctrl-top-left,.mapboxgl-ctrl-top-right{pointer-events:none;position:absolute;z-index:2}.mapboxgl-ctrl-top-left{left:0;top:0}.mapboxgl-ctrl-top{left:50%;top:0;transform:translateX(-50%)}.mapboxgl-ctrl-top-right{right:0;top:0}.mapboxgl-ctrl-right{right:0;top:50%;transform:translateY(-50%)}.mapboxgl-ctrl-bottom-right{bottom:0;right:0}.mapboxgl-ctrl-bottom{bottom:0;left:50%;transform:translateX(-50%)}.mapboxgl-ctrl-bottom-left{bottom:0;left:0}.mapboxgl-ctrl-left{left:0;top:50%;transform:translateY(-50%)}.mapboxgl-ctrl{clear:both;pointer-events:auto;transform:translate(0)}.mapboxgl-ctrl-top-left .mapboxgl-ctrl{float:left;margin:10px 0 0 10px}.mapboxgl-ctrl-top .mapboxgl-ctrl{float:left;margin:10px 0}.mapboxgl-ctrl-top-right .mapboxgl-ctrl{float:right;margin:10px 10px 0 0}.mapboxgl-ctrl-bottom-right .mapboxgl-ctrl,.mapboxgl-ctrl-right .mapboxgl-ctrl{float:right;margin:0 10px 10px 0}.mapboxgl-ctrl-bottom .mapboxgl-ctrl{float:left;margin:10px 0}.mapboxgl-ctrl-bottom-left .mapboxgl-ctrl,.mapboxgl-ctrl-left .mapboxgl-ctrl{float:left;margin:0 0 10px 10px}.mapboxgl-ctrl-group{background:#fff;border-radius:4px}.mapboxgl-ctrl-group:not(:empty){box-shadow:0 0 0 2px rgba(0,0,0,.1)}@media (-ms-high-contrast:active){.mapboxgl-ctrl-group:not(:empty){box-shadow:0 0 0 2px ButtonText}}.mapboxgl-ctrl-group button{background-color:transparent;border:0;box-sizing:border-box;cursor:pointer;display:block;height:29px;outline:none;overflow:hidden;padding:0;width:29px}.mapboxgl-ctrl-group button+button{border-top:1px solid #ddd}.mapboxgl-ctrl button .mapboxgl-ctrl-icon{background-position:50%;background-repeat:no-repeat;display:block;height:100%;width:100%}@media (-ms-high-contrast:active){.mapboxgl-ctrl-icon{background-color:transparent}.mapboxgl-ctrl-group button+button{border-top:1px solid ButtonText}}.mapboxgl-ctrl-attrib-button:focus,.mapboxgl-ctrl-group button:focus{box-shadow:0 0 2px 2px #0096ff}.mapboxgl-ctrl button:disabled{cursor:not-allowed}.mapboxgl-ctrl button:disabled .mapboxgl-ctrl-icon{opacity:.25}.mapboxgl-ctrl-group button:first-child{border-radius:4px 4px 0 0}.mapboxgl-ctrl-group button:last-child{border-radius:0 0 4px 4px}.mapboxgl-ctrl-group button:only-child{border-radius:inherit}.mapboxgl-ctrl button:not(:disabled):hover{background-color:rgb(0 0 0/5%)}.mapboxgl-ctrl-group button:focus:focus-visible{box-shadow:0 0 2px 2px #0096ff}.mapboxgl-ctrl-group button:focus:not(:focus-visible){box-shadow:none}.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-out .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-9z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-in .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5z'/%3E%3C/svg%3E")}@media (-ms-high-contrast:active){.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-out .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-9z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-in .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5z'/%3E%3C/svg%3E")}}@media (-ms-high-contrast:black-on-white){.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-out .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23000' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-9z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-in .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23000' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5z'/%3E%3C/svg%3E")}}.mapboxgl-ctrl button.mapboxgl-ctrl-fullscreen .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3h1zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16h1zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5H13zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1V7.5z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-shrink .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1h-5.5zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1v-5.5zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1v5.5zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1h5.5z'/%3E%3C/svg%3E")}@media (-ms-high-contrast:active){.mapboxgl-ctrl button.mapboxgl-ctrl-fullscreen .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3h1zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16h1zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5H13zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1V7.5z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-shrink .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1h-5.5zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1v-5.5zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1v5.5zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1h5.5z'/%3E%3C/svg%3E")}}@media (-ms-high-contrast:black-on-white){.mapboxgl-ctrl button.mapboxgl-ctrl-fullscreen .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23000' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3h1zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16h1zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5H13zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1V7.5z'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-shrink .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23000' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1h-5.5zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1v-5.5zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1v5.5zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1h5.5z'/%3E%3C/svg%3E")}}.mapboxgl-ctrl button.mapboxgl-ctrl-compass .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath id='south' d='M10.5 16l4 8 4-8h-8z' fill='%23ccc'/%3E%3C/svg%3E")}@media (-ms-high-contrast:active){.mapboxgl-ctrl button.mapboxgl-ctrl-compass .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath id='south' d='M10.5 16l4 8 4-8h-8z' fill='%23999'/%3E%3C/svg%3E")}}@media (-ms-high-contrast:black-on-white){.mapboxgl-ctrl button.mapboxgl-ctrl-compass .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23000' viewBox='0 0 29 29'%3E%3Cpath d='M10.5 14l4-8 4 8h-8z'/%3E%3Cpath id='south' d='M10.5 16l4 8 4-8h-8z' fill='%23ccc'/%3E%3C/svg%3E")}}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23333'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate:disabled .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23aaa'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' fill='%23f00'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%2333b5e5'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active-error .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23e58978'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%2333b5e5'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2' display='none'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background-error .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23e54e33'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2' display='none'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-waiting .mapboxgl-ctrl-icon{animation:mapboxgl-spin 2s linear infinite}@media (-ms-high-contrast:active){.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23fff'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate:disabled .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23999'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' fill='%23f00'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%2333b5e5'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-active-error .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23e58978'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%2333b5e5'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2' display='none'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate.mapboxgl-ctrl-geolocate-background-error .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23e54e33'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2' display='none'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}}@media (-ms-high-contrast:black-on-white){.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23000'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' display='none'/%3E%3C/svg%3E")}.mapboxgl-ctrl button.mapboxgl-ctrl-geolocate:disabled .mapboxgl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill='%23666'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1zm0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7z'/%3E%3Ccircle id='dot' cx='10' cy='10' r='2'/%3E%3Cpath id='stroke' d='M14 5l1 1-9 9-1-1 9-9z' fill='%23f00'/%3E%3C/svg%3E")}}@keyframes mapboxgl-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a.mapboxgl-ctrl-logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill-rule='evenodd' viewBox='0 0 88 23'%3E%3Cdefs%3E%3Cpath id='logo' d='M11.5 2.25c5.105 0 9.25 4.145 9.25 9.25s-4.145 9.25-9.25 9.25-9.25-4.145-9.25-9.25 4.145-9.25 9.25-9.25zM6.997 15.983c-.051-.338-.828-5.802 2.233-8.873a4.395 4.395 0 013.13-1.28c1.27 0 2.49.51 3.39 1.42.91.9 1.42 2.12 1.42 3.39 0 1.18-.449 2.301-1.28 3.13C12.72 16.93 7 16 7 16l-.003-.017zM15.3 10.5l-2 .8-.8 2-.8-2-2-.8 2-.8.8-2 .8 2 2 .8z'/%3E%3Cpath id='text' d='M50.63 8c.13 0 .23.1.23.23V9c.7-.76 1.7-1.18 2.73-1.18 2.17 0 3.95 1.85 3.95 4.17s-1.77 4.19-3.94 4.19c-1.04 0-2.03-.43-2.74-1.18v3.77c0 .13-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V8.23c0-.12.1-.23.23-.23h1.4zm-3.86.01c.01 0 .01 0 .01-.01.13 0 .22.1.22.22v7.55c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V15c-.7.76-1.69 1.19-2.73 1.19-2.17 0-3.94-1.87-3.94-4.19 0-2.32 1.77-4.19 3.94-4.19 1.03 0 2.02.43 2.73 1.18v-.75c0-.12.1-.23.23-.23h1.4zm26.375-.19a4.24 4.24 0 00-4.16 3.29c-.13.59-.13 1.19 0 1.77a4.233 4.233 0 004.17 3.3c2.35 0 4.26-1.87 4.26-4.19 0-2.32-1.9-4.17-4.27-4.17zM60.63 5c.13 0 .23.1.23.23v3.76c.7-.76 1.7-1.18 2.73-1.18 1.88 0 3.45 1.4 3.84 3.28.13.59.13 1.2 0 1.8-.39 1.88-1.96 3.29-3.84 3.29-1.03 0-2.02-.43-2.73-1.18v.77c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V5.23c0-.12.1-.23.23-.23h1.4zm-34 11h-1.4c-.13 0-.23-.11-.23-.23V8.22c.01-.13.1-.22.23-.22h1.4c.13 0 .22.11.23.22v.68c.5-.68 1.3-1.09 2.16-1.1h.03c1.09 0 2.09.6 2.6 1.55.45-.95 1.4-1.55 2.44-1.56 1.62 0 2.93 1.25 2.9 2.78l.03 5.2c0 .13-.1.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.8 0-1.46.7-1.59 1.62l.01 4.68c0 .13-.11.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.85 0-1.54.79-1.6 1.8v4.5c0 .13-.1.23-.23.23zm53.615 0h-1.61c-.04 0-.08-.01-.12-.03-.09-.06-.13-.19-.06-.28l2.43-3.71-2.39-3.65a.213.213 0 01-.03-.12c0-.12.09-.21.21-.21h1.61c.13 0 .24.06.3.17l1.41 2.37 1.4-2.37a.34.34 0 01.3-.17h1.6c.04 0 .08.01.12.03.09.06.13.19.06.28l-2.37 3.65 2.43 3.7c0 .05.01.09.01.13 0 .12-.09.21-.21.21h-1.61c-.13 0-.24-.06-.3-.17l-1.44-2.42-1.44 2.42a.34.34 0 01-.3.17zm-7.12-1.49c-1.33 0-2.42-1.12-2.42-2.51 0-1.39 1.08-2.52 2.42-2.52 1.33 0 2.42 1.12 2.42 2.51 0 1.39-1.08 2.51-2.42 2.52zm-19.865 0c-1.32 0-2.39-1.11-2.42-2.48v-.07c.02-1.38 1.09-2.49 2.4-2.49 1.32 0 2.41 1.12 2.41 2.51 0 1.39-1.07 2.52-2.39 2.53zm-8.11-2.48c-.01 1.37-1.09 2.47-2.41 2.47s-2.42-1.12-2.42-2.51c0-1.39 1.08-2.52 2.4-2.52 1.33 0 2.39 1.11 2.41 2.48l.02.08zm18.12 2.47c-1.32 0-2.39-1.11-2.41-2.48v-.06c.02-1.38 1.09-2.48 2.41-2.48s2.42 1.12 2.42 2.51c0 1.39-1.09 2.51-2.42 2.51z'/%3E%3C/defs%3E%3Cmask id='clip'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='white'/%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/mask%3E%3Cg id='outline' opacity='0.3' stroke='%23000' stroke-width='3'%3E%3Ccircle mask='url(%23clip)' cx='11.5' cy='11.5' r='9.25'/%3E%3Cuse xlink:href='%23text' mask='url(%23clip)'/%3E%3C/g%3E%3Cg id='fill' opacity='0.9' fill='%23fff'%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;cursor:pointer;display:block;height:23px;margin:0 0 -4px -4px;overflow:hidden;width:88px}a.mapboxgl-ctrl-logo.mapboxgl-compact{width:23px}@media (-ms-high-contrast:active){a.mapboxgl-ctrl-logo{background-color:transparent;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill-rule='evenodd' viewBox='0 0 88 23'%3E%3Cdefs%3E%3Cpath id='logo' d='M11.5 2.25c5.105 0 9.25 4.145 9.25 9.25s-4.145 9.25-9.25 9.25-9.25-4.145-9.25-9.25 4.145-9.25 9.25-9.25zM6.997 15.983c-.051-.338-.828-5.802 2.233-8.873a4.395 4.395 0 013.13-1.28c1.27 0 2.49.51 3.39 1.42.91.9 1.42 2.12 1.42 3.39 0 1.18-.449 2.301-1.28 3.13C12.72 16.93 7 16 7 16l-.003-.017zM15.3 10.5l-2 .8-.8 2-.8-2-2-.8 2-.8.8-2 .8 2 2 .8z'/%3E%3Cpath id='text' d='M50.63 8c.13 0 .23.1.23.23V9c.7-.76 1.7-1.18 2.73-1.18 2.17 0 3.95 1.85 3.95 4.17s-1.77 4.19-3.94 4.19c-1.04 0-2.03-.43-2.74-1.18v3.77c0 .13-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V8.23c0-.12.1-.23.23-.23h1.4zm-3.86.01c.01 0 .01 0 .01-.01.13 0 .22.1.22.22v7.55c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V15c-.7.76-1.69 1.19-2.73 1.19-2.17 0-3.94-1.87-3.94-4.19 0-2.32 1.77-4.19 3.94-4.19 1.03 0 2.02.43 2.73 1.18v-.75c0-.12.1-.23.23-.23h1.4zm26.375-.19a4.24 4.24 0 00-4.16 3.29c-.13.59-.13 1.19 0 1.77a4.233 4.233 0 004.17 3.3c2.35 0 4.26-1.87 4.26-4.19 0-2.32-1.9-4.17-4.27-4.17zM60.63 5c.13 0 .23.1.23.23v3.76c.7-.76 1.7-1.18 2.73-1.18 1.88 0 3.45 1.4 3.84 3.28.13.59.13 1.2 0 1.8-.39 1.88-1.96 3.29-3.84 3.29-1.03 0-2.02-.43-2.73-1.18v.77c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V5.23c0-.12.1-.23.23-.23h1.4zm-34 11h-1.4c-.13 0-.23-.11-.23-.23V8.22c.01-.13.1-.22.23-.22h1.4c.13 0 .22.11.23.22v.68c.5-.68 1.3-1.09 2.16-1.1h.03c1.09 0 2.09.6 2.6 1.55.45-.95 1.4-1.55 2.44-1.56 1.62 0 2.93 1.25 2.9 2.78l.03 5.2c0 .13-.1.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.8 0-1.46.7-1.59 1.62l.01 4.68c0 .13-.11.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.85 0-1.54.79-1.6 1.8v4.5c0 .13-.1.23-.23.23zm53.615 0h-1.61c-.04 0-.08-.01-.12-.03-.09-.06-.13-.19-.06-.28l2.43-3.71-2.39-3.65a.213.213 0 01-.03-.12c0-.12.09-.21.21-.21h1.61c.13 0 .24.06.3.17l1.41 2.37 1.4-2.37a.34.34 0 01.3-.17h1.6c.04 0 .08.01.12.03.09.06.13.19.06.28l-2.37 3.65 2.43 3.7c0 .05.01.09.01.13 0 .12-.09.21-.21.21h-1.61c-.13 0-.24-.06-.3-.17l-1.44-2.42-1.44 2.42a.34.34 0 01-.3.17zm-7.12-1.49c-1.33 0-2.42-1.12-2.42-2.51 0-1.39 1.08-2.52 2.42-2.52 1.33 0 2.42 1.12 2.42 2.51 0 1.39-1.08 2.51-2.42 2.52zm-19.865 0c-1.32 0-2.39-1.11-2.42-2.48v-.07c.02-1.38 1.09-2.49 2.4-2.49 1.32 0 2.41 1.12 2.41 2.51 0 1.39-1.07 2.52-2.39 2.53zm-8.11-2.48c-.01 1.37-1.09 2.47-2.41 2.47s-2.42-1.12-2.42-2.51c0-1.39 1.08-2.52 2.4-2.52 1.33 0 2.39 1.11 2.41 2.48l.02.08zm18.12 2.47c-1.32 0-2.39-1.11-2.41-2.48v-.06c.02-1.38 1.09-2.48 2.41-2.48s2.42 1.12 2.42 2.51c0 1.39-1.09 2.51-2.42 2.51z'/%3E%3C/defs%3E%3Cmask id='clip'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='white'/%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/mask%3E%3Cg id='outline' opacity='1' stroke='%23000' stroke-width='3'%3E%3Ccircle mask='url(%23clip)' cx='11.5' cy='11.5' r='9.25'/%3E%3Cuse xlink:href='%23text' mask='url(%23clip)'/%3E%3C/g%3E%3Cg id='fill' opacity='1' fill='%23fff'%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/g%3E%3C/svg%3E")}}@media (-ms-high-contrast:black-on-white){a.mapboxgl-ctrl-logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' fill-rule='evenodd' viewBox='0 0 88 23'%3E%3Cdefs%3E%3Cpath id='logo' d='M11.5 2.25c5.105 0 9.25 4.145 9.25 9.25s-4.145 9.25-9.25 9.25-9.25-4.145-9.25-9.25 4.145-9.25 9.25-9.25zM6.997 15.983c-.051-.338-.828-5.802 2.233-8.873a4.395 4.395 0 013.13-1.28c1.27 0 2.49.51 3.39 1.42.91.9 1.42 2.12 1.42 3.39 0 1.18-.449 2.301-1.28 3.13C12.72 16.93 7 16 7 16l-.003-.017zM15.3 10.5l-2 .8-.8 2-.8-2-2-.8 2-.8.8-2 .8 2 2 .8z'/%3E%3Cpath id='text' d='M50.63 8c.13 0 .23.1.23.23V9c.7-.76 1.7-1.18 2.73-1.18 2.17 0 3.95 1.85 3.95 4.17s-1.77 4.19-3.94 4.19c-1.04 0-2.03-.43-2.74-1.18v3.77c0 .13-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V8.23c0-.12.1-.23.23-.23h1.4zm-3.86.01c.01 0 .01 0 .01-.01.13 0 .22.1.22.22v7.55c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V15c-.7.76-1.69 1.19-2.73 1.19-2.17 0-3.94-1.87-3.94-4.19 0-2.32 1.77-4.19 3.94-4.19 1.03 0 2.02.43 2.73 1.18v-.75c0-.12.1-.23.23-.23h1.4zm26.375-.19a4.24 4.24 0 00-4.16 3.29c-.13.59-.13 1.19 0 1.77a4.233 4.233 0 004.17 3.3c2.35 0 4.26-1.87 4.26-4.19 0-2.32-1.9-4.17-4.27-4.17zM60.63 5c.13 0 .23.1.23.23v3.76c.7-.76 1.7-1.18 2.73-1.18 1.88 0 3.45 1.4 3.84 3.28.13.59.13 1.2 0 1.8-.39 1.88-1.96 3.29-3.84 3.29-1.03 0-2.02-.43-2.73-1.18v.77c0 .12-.1.23-.23.23h-1.4c-.13 0-.23-.1-.23-.23V5.23c0-.12.1-.23.23-.23h1.4zm-34 11h-1.4c-.13 0-.23-.11-.23-.23V8.22c.01-.13.1-.22.23-.22h1.4c.13 0 .22.11.23.22v.68c.5-.68 1.3-1.09 2.16-1.1h.03c1.09 0 2.09.6 2.6 1.55.45-.95 1.4-1.55 2.44-1.56 1.62 0 2.93 1.25 2.9 2.78l.03 5.2c0 .13-.1.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.8 0-1.46.7-1.59 1.62l.01 4.68c0 .13-.11.23-.23.23h-1.41c-.13 0-.23-.11-.23-.23v-4.59c0-.98-.74-1.71-1.62-1.71-.85 0-1.54.79-1.6 1.8v4.5c0 .13-.1.23-.23.23zm53.615 0h-1.61c-.04 0-.08-.01-.12-.03-.09-.06-.13-.19-.06-.28l2.43-3.71-2.39-3.65a.213.213 0 01-.03-.12c0-.12.09-.21.21-.21h1.61c.13 0 .24.06.3.17l1.41 2.37 1.4-2.37a.34.34 0 01.3-.17h1.6c.04 0 .08.01.12.03.09.06.13.19.06.28l-2.37 3.65 2.43 3.7c0 .05.01.09.01.13 0 .12-.09.21-.21.21h-1.61c-.13 0-.24-.06-.3-.17l-1.44-2.42-1.44 2.42a.34.34 0 01-.3.17zm-7.12-1.49c-1.33 0-2.42-1.12-2.42-2.51 0-1.39 1.08-2.52 2.42-2.52 1.33 0 2.42 1.12 2.42 2.51 0 1.39-1.08 2.51-2.42 2.52zm-19.865 0c-1.32 0-2.39-1.11-2.42-2.48v-.07c.02-1.38 1.09-2.49 2.4-2.49 1.32 0 2.41 1.12 2.41 2.51 0 1.39-1.07 2.52-2.39 2.53zm-8.11-2.48c-.01 1.37-1.09 2.47-2.41 2.47s-2.42-1.12-2.42-2.51c0-1.39 1.08-2.52 2.4-2.52 1.33 0 2.39 1.11 2.41 2.48l.02.08zm18.12 2.47c-1.32 0-2.39-1.11-2.41-2.48v-.06c.02-1.38 1.09-2.48 2.41-2.48s2.42 1.12 2.42 2.51c0 1.39-1.09 2.51-2.42 2.51z'/%3E%3C/defs%3E%3Cmask id='clip'%3E%3Crect x='0' y='0' width='100%25' height='100%25' fill='white'/%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/mask%3E%3Cg id='outline' opacity='1' stroke='%23fff' stroke-width='3' fill='%23fff'%3E%3Ccircle mask='url(%23clip)' cx='11.5' cy='11.5' r='9.25'/%3E%3Cuse xlink:href='%23text' mask='url(%23clip)'/%3E%3C/g%3E%3Cg id='fill' opacity='1' fill='%23000'%3E%3Cuse xlink:href='%23logo'/%3E%3Cuse xlink:href='%23text'/%3E%3C/g%3E%3C/svg%3E")}}.mapboxgl-ctrl.mapboxgl-ctrl-attrib{background-color:hsla(0,0%,100%,.5);margin:0;padding:0 5px}@media screen{.mapboxgl-ctrl-attrib.mapboxgl-compact{background-color:#fff;border-radius:12px;box-sizing:content-box;margin:10px;min-height:20px;padding:2px 24px 2px 0;position:relative}.mapboxgl-ctrl-attrib.mapboxgl-compact-show{padding:2px 28px 2px 8px;visibility:visible}.mapboxgl-ctrl-bottom-left>.mapboxgl-ctrl-attrib.mapboxgl-compact-show,.mapboxgl-ctrl-left>.mapboxgl-ctrl-attrib.mapboxgl-compact-show,.mapboxgl-ctrl-top-left>.mapboxgl-ctrl-attrib.mapboxgl-compact-show{border-radius:12px;padding:2px 8px 2px 28px}.mapboxgl-ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-inner{display:none}.mapboxgl-ctrl-attrib-button{background-color:hsla(0,0%,100%,.5);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E");border:0;border-radius:12px;box-sizing:border-box;cursor:pointer;display:none;height:24px;outline:none;position:absolute;right:0;top:0;width:24px}.mapboxgl-ctrl-bottom-left .mapboxgl-ctrl-attrib-button,.mapboxgl-ctrl-left .mapboxgl-ctrl-attrib-button,.mapboxgl-ctrl-top-left .mapboxgl-ctrl-attrib-button{left:0}.mapboxgl-ctrl-attrib.mapboxgl-compact .mapboxgl-ctrl-attrib-button,.mapboxgl-ctrl-attrib.mapboxgl-compact-show .mapboxgl-ctrl-attrib-inner{display:block}.mapboxgl-ctrl-attrib.mapboxgl-compact-show .mapboxgl-ctrl-attrib-button{background-color:rgb(0 0 0/5%)}.mapboxgl-ctrl-bottom-right>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{bottom:0;right:0}.mapboxgl-ctrl-right>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{right:0}.mapboxgl-ctrl-top-right>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{right:0;top:0}.mapboxgl-ctrl-top-left>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{left:0;top:0}.mapboxgl-ctrl-bottom-left>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{bottom:0;left:0}.mapboxgl-ctrl-left>.mapboxgl-ctrl-attrib.mapboxgl-compact:after{left:0}}@media screen and (-ms-high-contrast:active){.mapboxgl-ctrl-attrib.mapboxgl-compact:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd' fill='%23fff'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E")}}@media screen and (-ms-high-contrast:black-on-white){.mapboxgl-ctrl-attrib.mapboxgl-compact:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg' fill-rule='evenodd'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E")}}.mapboxgl-ctrl-attrib a{color:rgba(0,0,0,.75);text-decoration:none}.mapboxgl-ctrl-attrib a:hover{color:inherit;text-decoration:underline}.mapboxgl-ctrl-attrib .mapbox-improve-map{font-weight:700;margin-left:2px}.mapboxgl-attrib-empty{display:none}.mapboxgl-ctrl-scale{background-color:hsla(0,0%,100%,.75);border:2px solid #333;border-top:#333;box-sizing:border-box;color:#333;font-size:10px;padding:0 5px;white-space:nowrap}.mapboxgl-popup{display:flex;left:0;pointer-events:none;position:absolute;top:0;will-change:transform}.mapboxgl-popup-anchor-top,.mapboxgl-popup-anchor-top-left,.mapboxgl-popup-anchor-top-right{flex-direction:column}.mapboxgl-popup-anchor-bottom,.mapboxgl-popup-anchor-bottom-left,.mapboxgl-popup-anchor-bottom-right{flex-direction:column-reverse}.mapboxgl-popup-anchor-left{flex-direction:row}.mapboxgl-popup-anchor-right{flex-direction:row-reverse}.mapboxgl-popup-tip{border:10px solid transparent;height:0;width:0;z-index:1}.mapboxgl-popup-anchor-top .mapboxgl-popup-tip{align-self:center;border-bottom-color:#fff;border-top:none}.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip{align-self:flex-start;border-bottom-color:#fff;border-left:none;border-top:none}.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip{align-self:flex-end;border-bottom-color:#fff;border-right:none;border-top:none}.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip{align-self:center;border-bottom:none;border-top-color:#fff}.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip{align-self:flex-start;border-bottom:none;border-left:none;border-top-color:#fff}.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip{align-self:flex-end;border-bottom:none;border-right:none;border-top-color:#fff}.mapboxgl-popup-anchor-left .mapboxgl-popup-tip{align-self:center;border-left:none;border-right-color:#fff}.mapboxgl-popup-anchor-right .mapboxgl-popup-tip{align-self:center;border-left-color:#fff;border-right:none}.mapboxgl-popup-close-button{background-color:transparent;border:0;border-radius:0 3px 0 0;cursor:pointer;position:absolute;right:0;top:0}.mapboxgl-popup-close-button:hover{background-color:rgb(0 0 0/5%)}.mapboxgl-popup-content{background:#fff;border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.1);padding:10px 10px 15px;pointer-events:auto;position:relative}.mapboxgl-popup-anchor-top-left .mapboxgl-popup-content{border-top-left-radius:0}.mapboxgl-popup-anchor-top-right .mapboxgl-popup-content{border-top-right-radius:0}.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-content{border-bottom-left-radius:0}.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-content{border-bottom-right-radius:0}.mapboxgl-popup-track-pointer{display:none}.mapboxgl-popup-track-pointer *{pointer-events:none;user-select:none}.mapboxgl-map:hover .mapboxgl-popup-track-pointer{display:flex}.mapboxgl-map:active .mapboxgl-popup-track-pointer{display:none}.mapboxgl-marker{left:0;opacity:1;position:absolute;top:0;transition:opacity .2s;will-change:transform}.mapboxgl-user-location-dot,.mapboxgl-user-location-dot:before{background-color:#1da1f2;border-radius:50%;height:15px;width:15px}.mapboxgl-user-location-dot:before{animation:mapboxgl-user-location-dot-pulse 2s infinite;content:"";position:absolute}.mapboxgl-user-location-dot:after{border:2px solid #fff;border-radius:50%;box-shadow:0 0 3px rgba(0,0,0,.35);box-sizing:border-box;content:"";height:19px;left:-2px;position:absolute;top:-2px;width:19px}.mapboxgl-user-location-show-heading .mapboxgl-user-location-heading{height:0;width:0}.mapboxgl-user-location-show-heading .mapboxgl-user-location-heading:after,.mapboxgl-user-location-show-heading .mapboxgl-user-location-heading:before{border-bottom:7.5px solid #4aa1eb;content:"";position:absolute}.mapboxgl-user-location-show-heading .mapboxgl-user-location-heading:before{border-left:7.5px solid transparent;transform:translateY(-28px) skewY(-20deg)}.mapboxgl-user-location-show-heading .mapboxgl-user-location-heading:after{border-right:7.5px solid transparent;transform:translate(7.5px,-28px) skewY(20deg)}@keyframes mapboxgl-user-location-dot-pulse{0%{opacity:1;transform:scale(1)}70%{opacity:0;transform:scale(3)}to{opacity:0;transform:scale(1)}}.mapboxgl-user-location-dot-stale{background-color:#aaa}.mapboxgl-user-location-dot-stale:after{display:none}.mapboxgl-user-location-accuracy-circle{background-color:#1da1f233;border-radius:100%;height:1px;width:1px}.mapboxgl-crosshair,.mapboxgl-crosshair .mapboxgl-interactive,.mapboxgl-crosshair .mapboxgl-interactive:active{cursor:crosshair}.mapboxgl-boxzoom{background:#fff;border:2px dotted #202020;height:0;left:0;opacity:.5;position:absolute;top:0;width:0}@media print{.mapbox-improve-map{display:none}}.mapboxgl-scroll-zoom-blocker,.mapboxgl-touch-pan-blocker{align-items:center;background:rgba(0,0,0,.7);color:#fff;display:flex;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;height:100%;justify-content:center;left:0;opacity:0;pointer-events:none;position:absolute;text-align:center;top:0;transition:opacity .75s ease-in-out;transition-delay:1s;width:100%}.mapboxgl-scroll-zoom-blocker-show,.mapboxgl-touch-pan-blocker-show{opacity:1;transition:opacity .1s ease-in-out}.mapboxgl-canvas-container.mapboxgl-touch-pan-blocker-override.mapboxgl-scrollable-page,.mapboxgl-canvas-container.mapboxgl-touch-pan-blocker-override.mapboxgl-scrollable-page .mapboxgl-canvas{touch-action:pan-x pan-y} ================================================ FILE: website/src/maplibre-gl.css ================================================ .maplibregl-map{font:12px/20px Helvetica Neue,Arial,Helvetica,sans-serif;overflow:hidden;position:relative;-webkit-tap-highlight-color:rgb(0 0 0/0)}.maplibregl-canvas{left:0;position:absolute;top:0}.maplibregl-map:fullscreen{height:100%;width:100%}.maplibregl-ctrl-group button.maplibregl-ctrl-compass{touch-action:none}.maplibregl-canvas-container.maplibregl-interactive,.maplibregl-ctrl-group button.maplibregl-ctrl-compass{cursor:grab;-webkit-user-select:none;-moz-user-select:none;user-select:none}.maplibregl-canvas-container.maplibregl-interactive.maplibregl-track-pointer{cursor:pointer}.maplibregl-canvas-container.maplibregl-interactive:active,.maplibregl-ctrl-group button.maplibregl-ctrl-compass:active{cursor:grabbing}.maplibregl-canvas-container.maplibregl-touch-zoom-rotate,.maplibregl-canvas-container.maplibregl-touch-zoom-rotate .maplibregl-canvas{touch-action:pan-x pan-y}.maplibregl-canvas-container.maplibregl-touch-drag-pan,.maplibregl-canvas-container.maplibregl-touch-drag-pan .maplibregl-canvas{touch-action:pinch-zoom}.maplibregl-canvas-container.maplibregl-touch-zoom-rotate.maplibregl-touch-drag-pan,.maplibregl-canvas-container.maplibregl-touch-zoom-rotate.maplibregl-touch-drag-pan .maplibregl-canvas{touch-action:none}.maplibregl-canvas-container.maplibregl-touch-drag-pan.maplibregl-cooperative-gestures,.maplibregl-canvas-container.maplibregl-touch-drag-pan.maplibregl-cooperative-gestures .maplibregl-canvas{touch-action:pan-x pan-y}.maplibregl-ctrl-bottom-left,.maplibregl-ctrl-bottom-right,.maplibregl-ctrl-top-left,.maplibregl-ctrl-top-right{pointer-events:none;position:absolute;z-index:2}.maplibregl-ctrl-top-left{left:0;top:0}.maplibregl-ctrl-top-right{right:0;top:0}.maplibregl-ctrl-bottom-left{bottom:0;left:0}.maplibregl-ctrl-bottom-right{bottom:0;right:0}.maplibregl-ctrl{clear:both;pointer-events:auto;transform:translate(0)}.maplibregl-ctrl-top-left .maplibregl-ctrl{float:left;margin:10px 0 0 10px}.maplibregl-ctrl-top-right .maplibregl-ctrl{float:right;margin:10px 10px 0 0}.maplibregl-ctrl-bottom-left .maplibregl-ctrl{float:left;margin:0 0 10px 10px}.maplibregl-ctrl-bottom-right .maplibregl-ctrl{float:right;margin:0 10px 10px 0}.maplibregl-ctrl-group{background:#fff;border-radius:4px}.maplibregl-ctrl-group:not(:empty){box-shadow:0 0 0 2px rgba(0,0,0,.1)}@media (forced-colors:active){.maplibregl-ctrl-group:not(:empty){box-shadow:0 0 0 2px ButtonText}}.maplibregl-ctrl-group button{background-color:transparent;border:0;box-sizing:border-box;cursor:pointer;display:block;height:29px;outline:none;padding:0;width:29px}.maplibregl-ctrl-group button+button{border-top:1px solid #ddd}.maplibregl-ctrl button .maplibregl-ctrl-icon{background-position:50%;background-repeat:no-repeat;display:block;height:100%;width:100%}@media (forced-colors:active){.maplibregl-ctrl-icon{background-color:transparent}.maplibregl-ctrl-group button+button{border-top:1px solid ButtonText}}.maplibregl-ctrl button::-moz-focus-inner{border:0;padding:0}.maplibregl-ctrl-attrib-button:focus,.maplibregl-ctrl-group button:focus{box-shadow:0 0 2px 2px #0096ff}.maplibregl-ctrl button:disabled{cursor:not-allowed}.maplibregl-ctrl button:disabled .maplibregl-ctrl-icon{opacity:.25}.maplibregl-ctrl button:not(:disabled):hover{background-color:rgb(0 0 0/5%)}.maplibregl-ctrl-group button:focus:focus-visible{box-shadow:0 0 2px 2px #0096ff}.maplibregl-ctrl-group button:focus:not(:focus-visible){box-shadow:none}.maplibregl-ctrl-group button:focus:first-child{border-radius:4px 4px 0 0}.maplibregl-ctrl-group button:focus:last-child{border-radius:0 0 4px 4px}.maplibregl-ctrl-group button:focus:only-child{border-radius:inherit}.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5'/%3E%3C/svg%3E")}@media (forced-colors:active){.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5'/%3E%3C/svg%3E")}}@media (forced-colors:active) and (prefers-color-scheme:light){.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='M10 13c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h9c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='M14.5 8.5c-.75 0-1.5.75-1.5 1.5v3h-3c-.75 0-1.5.75-1.5 1.5S9.25 16 10 16h3v3c0 .75.75 1.5 1.5 1.5S16 19.75 16 19v-3h3c.75 0 1.5-.75 1.5-1.5S19.75 13 19 13h-3v-3c0-.75-.75-1.5-1.5-1.5'/%3E%3C/svg%3E")}}.maplibregl-ctrl button.maplibregl-ctrl-fullscreen .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-shrink .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1z'/%3E%3C/svg%3E")}@media (forced-colors:active){.maplibregl-ctrl button.maplibregl-ctrl-fullscreen .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-shrink .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1z'/%3E%3C/svg%3E")}}@media (forced-colors:active) and (prefers-color-scheme:light){.maplibregl-ctrl button.maplibregl-ctrl-fullscreen .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='M24 16v5.5c0 1.75-.75 2.5-2.5 2.5H16v-1l3-1.5-4-5.5 1-1 5.5 4 1.5-3zM6 16l1.5 3 5.5-4 1 1-4 5.5 3 1.5v1H7.5C5.75 24 5 23.25 5 21.5V16zm7-11v1l-3 1.5 4 5.5-1 1-5.5-4L6 13H5V7.5C5 5.75 5.75 5 7.5 5zm11 2.5c0-1.75-.75-2.5-2.5-2.5H16v1l3 1.5-4 5.5 1 1 5.5-4 1.5 3h1z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-shrink .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='M18.5 16c-1.75 0-2.5.75-2.5 2.5V24h1l1.5-3 5.5 4 1-1-4-5.5 3-1.5v-1zM13 18.5c0-1.75-.75-2.5-2.5-2.5H5v1l3 1.5L4 24l1 1 5.5-4 1.5 3h1zm3-8c0 1.75.75 2.5 2.5 2.5H24v-1l-3-1.5L25 5l-1-1-5.5 4L17 5h-1zM10.5 13c1.75 0 2.5-.75 2.5-2.5V5h-1l-1.5 3L5 4 4 5l4 5.5L5 12v1z'/%3E%3C/svg%3E")}}.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 29 29'%3E%3Cpath d='m10.5 14 4-8 4 8z'/%3E%3Cpath fill='%23ccc' d='m10.5 16 4 8 4-8z'/%3E%3C/svg%3E")}@media (forced-colors:active){.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 29 29'%3E%3Cpath d='m10.5 14 4-8 4 8z'/%3E%3Cpath fill='%23ccc' d='m10.5 16 4 8 4-8z'/%3E%3C/svg%3E")}}@media (forced-colors:active) and (prefers-color-scheme:light){.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 29 29'%3E%3Cpath d='m10.5 14 4-8 4 8z'/%3E%3Cpath fill='%23ccc' d='m10.5 16 4 8 4-8z'/%3E%3C/svg%3E")}}.maplibregl-ctrl button.maplibregl-ctrl-terrain .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' fill='%23333' viewBox='0 0 22 22'%3E%3Cpath d='m1.754 13.406 4.453-4.851 3.09 3.09 3.281 3.277.969-.969-3.309-3.312 3.844-4.121 6.148 6.886h1.082v-.855l-7.207-8.07-4.84 5.187L6.169 6.57l-5.48 5.965v.871ZM.688 16.844h20.625v1.375H.688Zm0 0'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-terrain-enabled .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='22' height='22' fill='%2333b5e5' viewBox='0 0 22 22'%3E%3Cpath d='m1.754 13.406 4.453-4.851 3.09 3.09 3.281 3.277.969-.969-3.309-3.312 3.844-4.121 6.148 6.886h1.082v-.855l-7.207-8.07-4.84 5.187L6.169 6.57l-5.48 5.965v.871ZM.688 16.844h20.625v1.375H.688Zm0 0'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23333' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate:disabled .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23aaa' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3Cpath fill='red' d='m14 5 1 1-9 9-1-1z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%2333b5e5' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active-error .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23e58978' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%2333b5e5' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background-error .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23e54e33' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-waiting .maplibregl-ctrl-icon{animation:maplibregl-spin 2s linear infinite}@media (forced-colors:active){.maplibregl-ctrl button.maplibregl-ctrl-geolocate .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23fff' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate:disabled .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23999' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3Cpath fill='red' d='m14 5 1 1-9 9-1-1z'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%2333b5e5' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-active-error .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23e58978' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%2333b5e5' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate.maplibregl-ctrl-geolocate-background-error .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23e54e33' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3C/svg%3E")}}@media (forced-colors:active) and (prefers-color-scheme:light){.maplibregl-ctrl button.maplibregl-ctrl-geolocate .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3C/svg%3E")}.maplibregl-ctrl button.maplibregl-ctrl-geolocate:disabled .maplibregl-ctrl-icon{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='29' height='29' fill='%23666' viewBox='0 0 20 20'%3E%3Cpath d='M10 4C9 4 9 5 9 5v.1A5 5 0 0 0 5.1 9H5s-1 0-1 1 1 1 1 1h.1A5 5 0 0 0 9 14.9v.1s0 1 1 1 1-1 1-1v-.1a5 5 0 0 0 3.9-3.9h.1s1 0 1-1-1-1-1-1h-.1A5 5 0 0 0 11 5.1V5s0-1-1-1m0 2.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 1 1 0-7'/%3E%3Ccircle cx='10' cy='10' r='2'/%3E%3Cpath fill='red' d='m14 5 1 1-9 9-1-1z'/%3E%3C/svg%3E")}}@keyframes maplibregl-spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a.maplibregl-ctrl-logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='23' fill='none'%3E%3Cpath fill='%23000' fill-opacity='.4' fill-rule='evenodd' d='M17.408 16.796h-1.827l2.501-12.095h.198l3.324 6.533.988 2.19.988-2.19 3.258-6.533h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.929 5.644h-.098l-2.914-5.644-.757-1.71-.345 1.71zm1.958-3.42-.726 3.663a1.255 1.255 0 0 1-1.232 1.011h-1.827a1.255 1.255 0 0 1-1.229-1.509l2.501-12.095a1.255 1.255 0 0 1 1.23-1.001h.197a1.25 1.25 0 0 1 1.12.685l3.19 6.273 3.125-6.263a1.25 1.25 0 0 1 1.123-.695h.181a1.255 1.255 0 0 1 1.227.991l1.443 6.71a5 5 0 0 1 .314-.787l.009-.016a4.6 4.6 0 0 1 1.777-1.887c.782-.46 1.668-.667 2.611-.667a4.6 4.6 0 0 1 1.7.32l.306.134c.21-.16.474-.256.759-.256h1.694a1.255 1.255 0 0 1 1.212.925 1.255 1.255 0 0 1 1.212-.925h1.711c.284 0 .545.094.755.252.613-.3 1.312-.45 2.075-.45 1.356 0 2.557.445 3.482 1.4q.47.48.763 1.064V4.701a1.255 1.255 0 0 1 1.255-1.255h1.86A1.255 1.255 0 0 1 54.44 4.7v9.194h2.217c.19 0 .37.043.532.118v-4.77c0-.356.147-.678.385-.906a2.42 2.42 0 0 1-.682-1.71c0-.665.267-1.253.735-1.7a2.45 2.45 0 0 1 1.722-.674 2.43 2.43 0 0 1 1.705.675q.318.302.504.683V4.7a1.255 1.255 0 0 1 1.255-1.255h1.744A1.255 1.255 0 0 1 65.812 4.7v3.335a4.8 4.8 0 0 1 1.526-.246c.938 0 1.817.214 2.59.69a4.47 4.47 0 0 1 1.67 1.743v-.98a1.255 1.255 0 0 1 1.256-1.256h1.777c.233 0 .451.064.639.174a3.4 3.4 0 0 1 1.567-.372c.346 0 .861.02 1.285.232a1.25 1.25 0 0 1 .689 1.004 4.7 4.7 0 0 1 .853-.588c.795-.44 1.675-.647 2.61-.647 1.385 0 2.65.39 3.525 1.396.836.938 1.168 2.173 1.168 3.528q-.001.515-.056 1.051a1.255 1.255 0 0 1-.947 1.09l.408.952a1.255 1.255 0 0 1-.477 1.552c-.418.268-.92.463-1.458.612-.613.171-1.304.244-2.049.244-1.06 0-2.043-.207-2.886-.698l-.015-.008c-.798-.48-1.419-1.135-1.818-1.963l-.004-.008a5.8 5.8 0 0 1-.548-2.512q0-.429.053-.843a1.3 1.3 0 0 1-.333-.086l-.166-.004c-.223 0-.426.062-.643.228-.03.024-.142.139-.142.59v3.883a1.255 1.255 0 0 1-1.256 1.256h-1.777a1.255 1.255 0 0 1-1.256-1.256V15.69l-.032.057a4.8 4.8 0 0 1-1.86 1.833 5.04 5.04 0 0 1-2.484.634 4.5 4.5 0 0 1-1.935-.424 1.25 1.25 0 0 1-.764.258h-1.71a1.255 1.255 0 0 1-1.256-1.255V7.687a2.4 2.4 0 0 1-.428.625c.253.23.412.561.412.93v7.553a1.255 1.255 0 0 1-1.256 1.255h-1.843a1.25 1.25 0 0 1-.894-.373c-.228.23-.544.373-.894.373H51.32a1.255 1.255 0 0 1-1.256-1.255v-1.251l-.061.117a4.7 4.7 0 0 1-1.782 1.884 4.77 4.77 0 0 1-2.485.67 5.6 5.6 0 0 1-1.485-.188l.009 2.764a1.255 1.255 0 0 1-1.255 1.259h-1.729a1.255 1.255 0 0 1-1.255-1.255v-3.537a1.255 1.255 0 0 1-1.167.793h-1.679a1.25 1.25 0 0 1-.77-.263 4.5 4.5 0 0 1-1.945.429c-.885 0-1.724-.21-2.495-.632l-.017-.01a5 5 0 0 1-1.081-.836 1.255 1.255 0 0 1-1.254 1.312h-1.81a1.255 1.255 0 0 1-1.228-.99l-.782-3.625-2.044 3.939a1.25 1.25 0 0 1-1.115.676h-.098a1.25 1.25 0 0 1-1.116-.68l-2.061-3.994zM35.92 16.63l.207-.114.223-.15q.493-.356.735-.785l.061-.118.033 1.332h1.678V9.242h-1.694l-.033 1.267q-.133-.329-.526-.658l-.032-.028a3.2 3.2 0 0 0-.668-.428l-.27-.12a3.3 3.3 0 0 0-1.235-.23q-1.136-.001-1.974.493a3.36 3.36 0 0 0-1.3 1.382q-.445.89-.444 2.074 0 1.2.51 2.107a3.8 3.8 0 0 0 1.382 1.381 3.9 3.9 0 0 0 1.893.477q.795 0 1.455-.33zm-2.789-5.38q-.576.675-.575 1.762 0 1.102.559 1.794.576.675 1.645.675a2.25 2.25 0 0 0 .934-.19 2.2 2.2 0 0 0 .468-.29l.178-.161a2.2 2.2 0 0 0 .397-.561q.244-.5.244-1.15v-.115q0-.708-.296-1.267l-.043-.077a2.2 2.2 0 0 0-.633-.709l-.13-.086-.047-.028a2.1 2.1 0 0 0-1.073-.285q-1.052 0-1.629.692zm2.316 2.706c.163-.17.28-.407.28-.83v-.114c0-.292-.06-.508-.15-.68a.96.96 0 0 0-.353-.389.85.85 0 0 0-.464-.127c-.4 0-.56.114-.664.239l-.01.012c-.148.174-.275.45-.275.945 0 .506.122.801.27.99.097.11.266.224.68.224.303 0 .504-.09.687-.269zm7.545 1.705a2.6 2.6 0 0 0 .331.423q.319.33.755.548l.173.074q.65.255 1.49.255 1.02 0 1.844-.493a3.45 3.45 0 0 0 1.316-1.4q.493-.904.493-2.089 0-1.909-.988-2.913-.988-1.02-2.584-1.02-.898 0-1.575.347a3 3 0 0 0-.415.262l-.199.166a3.4 3.4 0 0 0-.64.82V9.242h-1.712v11.553h1.729l-.017-5.134zm.53-1.138q.206.29.48.5l.155.11.053.034q.51.296 1.119.297 1.07 0 1.645-.675.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.435 0-.835.16a2 2 0 0 0-.284.136 2 2 0 0 0-.363.254 2.2 2.2 0 0 0-.46.569l-.082.162a2.6 2.6 0 0 0-.213 1.072v.115q0 .707.296 1.267l.135.211zm.964-.818a1.1 1.1 0 0 0 .367.385.94.94 0 0 0 .476.118c.423 0 .59-.117.687-.23.159-.194.28-.478.28-.95 0-.53-.133-.8-.266-.952l-.021-.025c-.078-.094-.231-.221-.68-.221a1 1 0 0 0-.503.135l-.012.007a.86.86 0 0 0-.335.343c-.073.133-.132.324-.132.614v.115a1.4 1.4 0 0 0 .14.66zm15.7-6.222q.347-.346.346-.856a1.05 1.05 0 0 0-.345-.79 1.18 1.18 0 0 0-.84-.329q-.51 0-.855.33a1.05 1.05 0 0 0-.346.79q0 .51.346.855.345.346.856.346.51 0 .839-.346zm4.337 9.314.033-1.332q.191.403.59.747l.098.081a4 4 0 0 0 .316.224l.223.122a3.2 3.2 0 0 0 1.44.322 3.8 3.8 0 0 0 1.875-.477 3.5 3.5 0 0 0 1.382-1.366q.527-.89.526-2.09 0-1.184-.444-2.073a3.24 3.24 0 0 0-1.283-1.399q-.823-.51-1.942-.51a3.5 3.5 0 0 0-1.527.344l-.086.043-.165.09a3 3 0 0 0-.33.214q-.432.315-.656.707a2 2 0 0 0-.099.198l.082-1.283V4.701h-1.744v12.095zm.473-2.509a2.5 2.5 0 0 0 .566.7q.117.098.245.18l.144.08a2.1 2.1 0 0 0 .975.232q1.07 0 1.645-.675.576-.69.576-1.778 0-1.102-.576-1.777-.56-.691-1.645-.692a2.2 2.2 0 0 0-1.015.235q-.22.113-.415.282l-.15.142a2.1 2.1 0 0 0-.42.594q-.223.479-.223 1.1v.115q0 .705.293 1.26zm2.616-.293c.157-.191.28-.479.28-.967 0-.51-.13-.79-.276-.961l-.021-.026c-.082-.1-.232-.225-.67-.225a.87.87 0 0 0-.681.279l-.012.011c-.154.155-.274.38-.274.807v.115c0 .285.057.499.144.669a1.1 1.1 0 0 0 .367.405c.137.082.28.123.455.123.423 0 .59-.118.686-.23zm8.266-3.013q.345-.13.724-.14l.069-.002q.493 0 .642.099l.247-1.794q-.196-.099-.717-.099a2.3 2.3 0 0 0-.545.063 2 2 0 0 0-.411.148 2.2 2.2 0 0 0-.4.249 2.5 2.5 0 0 0-.485.499 2.7 2.7 0 0 0-.32.581l-.05.137v-1.48h-1.778v7.553h1.777v-3.884q0-.546.159-.943a1.5 1.5 0 0 1 .466-.636 2.5 2.5 0 0 1 .399-.253 2 2 0 0 1 .224-.099zm9.784 2.656.05-.922q0-1.743-.856-2.698-.838-.97-2.584-.97-1.119-.001-2.007.493a3.46 3.46 0 0 0-1.4 1.382q-.493.906-.493 2.106 0 1.07.428 1.975.428.89 1.332 1.432.906.526 2.255.526.973 0 1.668-.185l.044-.012.135-.04q.613-.184.984-.421l-.542-1.267q-.3.162-.642.274l-.297.087q-.51.131-1.3.131-.954 0-1.497-.444a1.6 1.6 0 0 1-.192-.193q-.366-.44-.512-1.234l-.004-.021zm-5.427-1.256-.003.022h3.752v-.138q-.011-.727-.288-1.118a1 1 0 0 0-.156-.176q-.46-.428-1.316-.428-.986 0-1.494.604-.379.45-.494 1.234zm-27.053 2.77V4.7h-1.86v12.095h5.333V15.15zm7.103-5.908v7.553h-1.843V9.242h1.843z'/%3E%3Cpath fill='%23fff' d='m19.63 11.151-.757-1.71-.345 1.71-1.12 5.644h-1.827L18.083 4.7h.197l3.325 6.533.988 2.19.988-2.19L26.839 4.7h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.93 5.644h-.098l-2.913-5.644zm14.836 5.81q-1.02 0-1.893-.478a3.8 3.8 0 0 1-1.381-1.382q-.51-.906-.51-2.106 0-1.185.444-2.074a3.36 3.36 0 0 1 1.3-1.382q.839-.494 1.974-.494a3.3 3.3 0 0 1 1.234.231 3.3 3.3 0 0 1 .97.575q.396.33.527.659l.033-1.267h1.694v7.553H37.18l-.033-1.332q-.279.593-1.02 1.053a3.17 3.17 0 0 1-1.662.444zm.296-1.482q.938 0 1.58-.642.642-.66.642-1.711v-.115q0-.708-.296-1.267a2.2 2.2 0 0 0-.807-.872 2.1 2.1 0 0 0-1.119-.313q-1.053 0-1.629.692-.575.675-.575 1.76 0 1.103.559 1.795.577.675 1.645.675zm6.521-6.237h1.711v1.4q.906-1.597 2.83-1.597 1.596 0 2.584 1.02.988 1.005.988 2.914 0 1.185-.493 2.09a3.46 3.46 0 0 1-1.316 1.399 3.5 3.5 0 0 1-1.844.493q-.954 0-1.662-.329a2.67 2.67 0 0 1-1.086-.97l.017 5.134h-1.728zm4.048 6.22q1.07 0 1.645-.674.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.592 0-1.12.296-.51.28-.822.823-.296.527-.296 1.234v.115q0 .708.296 1.267.313.543.823.855.51.296 1.119.297z'/%3E%3Cpath fill='%23e1e3e9' d='M51.325 4.7h1.86v10.45h3.473v1.646h-5.333zm7.12 4.542h1.843v7.553h-1.843zm.905-1.415a1.16 1.16 0 0 1-.856-.346 1.17 1.17 0 0 1-.346-.856 1.05 1.05 0 0 1 .346-.79q.346-.329.856-.329.494 0 .839.33a1.05 1.05 0 0 1 .345.79 1.16 1.16 0 0 1-.345.855q-.33.346-.84.346zm7.875 9.133a3.17 3.17 0 0 1-1.662-.444q-.723-.46-1.004-1.053l-.033 1.332h-1.71V4.701h1.743v4.657l-.082 1.283q.279-.658 1.086-1.119a3.5 3.5 0 0 1 1.778-.477q1.119 0 1.942.51a3.24 3.24 0 0 1 1.283 1.4q.445.888.444 2.072 0 1.201-.526 2.09a3.5 3.5 0 0 1-1.382 1.366 3.8 3.8 0 0 1-1.876.477zm-.296-1.481q1.069 0 1.645-.675.577-.69.577-1.778 0-1.102-.577-1.776-.56-.691-1.645-.692a2.12 2.12 0 0 0-1.58.659q-.642.641-.642 1.694v.115q0 .71.296 1.267a2.4 2.4 0 0 0 .807.872 2.1 2.1 0 0 0 1.119.313zm5.927-6.237h1.777v1.481q.263-.757.856-1.217a2.14 2.14 0 0 1 1.349-.46q.527 0 .724.098l-.247 1.794q-.149-.099-.642-.099-.774 0-1.416.494-.626.493-.626 1.58v3.883h-1.777V9.242zm9.534 7.718q-1.35 0-2.255-.526-.904-.543-1.332-1.432a4.6 4.6 0 0 1-.428-1.975q0-1.2.493-2.106a3.46 3.46 0 0 1 1.4-1.382q.889-.495 2.007-.494 1.744 0 2.584.97.855.956.856 2.7 0 .444-.05.92h-5.43q.18 1.005.708 1.45.542.443 1.497.443.79 0 1.3-.131a4 4 0 0 0 .938-.362l.542 1.267q-.411.263-1.119.46-.708.198-1.711.197zm1.596-4.558q.016-1.02-.444-1.432-.46-.428-1.316-.428-1.728 0-1.991 1.86z'/%3E%3Cpath d='M5.074 15.948a.484.657 0 0 0-.486.659v1.84a.484.657 0 0 0 .486.659h4.101a.484.657 0 0 0 .486-.659v-1.84a.484.657 0 0 0-.486-.659zm3.56 1.16H5.617v.838h3.017z' style='fill:%23fff;fill-rule:evenodd;stroke-width:1.03600001'/%3E%3Cg style='stroke-width:1.12603545'%3E%3Cpath d='M-9.408-1.416c-3.833-.025-7.056 2.912-7.08 6.615-.02 3.08 1.653 4.832 3.107 6.268.903.892 1.721 1.74 2.32 2.902l-.525-.004c-.543-.003-.992.304-1.24.639a1.87 1.87 0 0 0-.362 1.121l-.011 1.877c-.003.402.104.787.347 1.125.244.338.688.653 1.23.656l4.142.028c.542.003.99-.306 1.238-.641a1.87 1.87 0 0 0 .363-1.121l.012-1.875a1.87 1.87 0 0 0-.348-1.127c-.243-.338-.688-.653-1.23-.656l-.518-.004c.597-1.145 1.425-1.983 2.348-2.87 1.473-1.414 3.18-3.149 3.2-6.226-.016-3.59-2.923-6.684-6.993-6.707m-.006 1.1v.002c3.274.02 5.92 2.532 5.9 5.6-.017 2.706-1.39 4.026-2.863 5.44-1.034.994-2.118 2.033-2.814 3.633-.018.041-.052.055-.075.065q-.013.004-.02.01a.34.34 0 0 1-.226.084.34.34 0 0 1-.224-.086l-.092-.077c-.699-1.615-1.768-2.669-2.781-3.67-1.454-1.435-2.797-2.762-2.78-5.478.02-3.067 2.7-5.545 5.975-5.523m-.02 2.826c-1.62-.01-2.944 1.315-2.955 2.96-.01 1.646 1.295 2.988 2.916 2.999h.002c1.621.01 2.943-1.316 2.953-2.961.011-1.646-1.294-2.988-2.916-2.998m-.005 1.1c1.017.006 1.829.83 1.822 1.89s-.83 1.874-1.848 1.867c-1.018-.006-1.829-.83-1.822-1.89s.83-1.874 1.848-1.868m-2.155 11.857 4.14.025c.271.002.49.305.487.676l-.013 1.875c-.003.37-.224.67-.495.668l-4.14-.025c-.27-.002-.487-.306-.485-.676l.012-1.875c.003-.37.224-.67.494-.668' style='color:%23000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:%23000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:evenodd;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:%23000;solid-opacity:1;vector-effect:none;fill:%23000;fill-opacity:.4;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-9.415-.316C-12.69-.338-15.37 2.14-15.39 5.207c-.017 2.716 1.326 4.041 2.78 5.477 1.013 1 2.081 2.055 2.78 3.67l.092.076a.34.34 0 0 0 .225.086.34.34 0 0 0 .227-.083l.019-.01c.022-.009.057-.024.074-.064.697-1.6 1.78-2.64 2.814-3.634 1.473-1.414 2.847-2.733 2.864-5.44.02-3.067-2.627-5.58-5.901-5.601m-.057 8.784c1.621.011 2.944-1.315 2.955-2.96.01-1.646-1.295-2.988-2.916-2.999-1.622-.01-2.945 1.315-2.955 2.96s1.295 2.989 2.916 3' style='clip-rule:evenodd;fill:%23e1e3e9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-11.594 15.465c-.27-.002-.492.297-.494.668l-.012 1.876c-.003.371.214.673.485.675l4.14.027c.271.002.492-.298.495-.668l.012-1.877c.003-.37-.215-.672-.485-.674z' style='clip-rule:evenodd;fill:%23fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3C/g%3E%3C/svg%3E");background-repeat:no-repeat;cursor:pointer;display:block;height:23px;margin:0 0 -4px -4px;overflow:hidden;width:88px}a.maplibregl-ctrl-logo.maplibregl-compact{width:14px}@media (forced-colors:active){a.maplibregl-ctrl-logo{background-color:transparent;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='23' fill='none'%3E%3Cpath fill='%23000' fill-opacity='.4' fill-rule='evenodd' d='M17.408 16.796h-1.827l2.501-12.095h.198l3.324 6.533.988 2.19.988-2.19 3.258-6.533h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.929 5.644h-.098l-2.914-5.644-.757-1.71-.345 1.71zm1.958-3.42-.726 3.663a1.255 1.255 0 0 1-1.232 1.011h-1.827a1.255 1.255 0 0 1-1.229-1.509l2.501-12.095a1.255 1.255 0 0 1 1.23-1.001h.197a1.25 1.25 0 0 1 1.12.685l3.19 6.273 3.125-6.263a1.25 1.25 0 0 1 1.123-.695h.181a1.255 1.255 0 0 1 1.227.991l1.443 6.71a5 5 0 0 1 .314-.787l.009-.016a4.6 4.6 0 0 1 1.777-1.887c.782-.46 1.668-.667 2.611-.667a4.6 4.6 0 0 1 1.7.32l.306.134c.21-.16.474-.256.759-.256h1.694a1.255 1.255 0 0 1 1.212.925 1.255 1.255 0 0 1 1.212-.925h1.711c.284 0 .545.094.755.252.613-.3 1.312-.45 2.075-.45 1.356 0 2.557.445 3.482 1.4q.47.48.763 1.064V4.701a1.255 1.255 0 0 1 1.255-1.255h1.86A1.255 1.255 0 0 1 54.44 4.7v9.194h2.217c.19 0 .37.043.532.118v-4.77c0-.356.147-.678.385-.906a2.42 2.42 0 0 1-.682-1.71c0-.665.267-1.253.735-1.7a2.45 2.45 0 0 1 1.722-.674 2.43 2.43 0 0 1 1.705.675q.318.302.504.683V4.7a1.255 1.255 0 0 1 1.255-1.255h1.744A1.255 1.255 0 0 1 65.812 4.7v3.335a4.8 4.8 0 0 1 1.526-.246c.938 0 1.817.214 2.59.69a4.47 4.47 0 0 1 1.67 1.743v-.98a1.255 1.255 0 0 1 1.256-1.256h1.777c.233 0 .451.064.639.174a3.4 3.4 0 0 1 1.567-.372c.346 0 .861.02 1.285.232a1.25 1.25 0 0 1 .689 1.004 4.7 4.7 0 0 1 .853-.588c.795-.44 1.675-.647 2.61-.647 1.385 0 2.65.39 3.525 1.396.836.938 1.168 2.173 1.168 3.528q-.001.515-.056 1.051a1.255 1.255 0 0 1-.947 1.09l.408.952a1.255 1.255 0 0 1-.477 1.552c-.418.268-.92.463-1.458.612-.613.171-1.304.244-2.049.244-1.06 0-2.043-.207-2.886-.698l-.015-.008c-.798-.48-1.419-1.135-1.818-1.963l-.004-.008a5.8 5.8 0 0 1-.548-2.512q0-.429.053-.843a1.3 1.3 0 0 1-.333-.086l-.166-.004c-.223 0-.426.062-.643.228-.03.024-.142.139-.142.59v3.883a1.255 1.255 0 0 1-1.256 1.256h-1.777a1.255 1.255 0 0 1-1.256-1.256V15.69l-.032.057a4.8 4.8 0 0 1-1.86 1.833 5.04 5.04 0 0 1-2.484.634 4.5 4.5 0 0 1-1.935-.424 1.25 1.25 0 0 1-.764.258h-1.71a1.255 1.255 0 0 1-1.256-1.255V7.687a2.4 2.4 0 0 1-.428.625c.253.23.412.561.412.93v7.553a1.255 1.255 0 0 1-1.256 1.255h-1.843a1.25 1.25 0 0 1-.894-.373c-.228.23-.544.373-.894.373H51.32a1.255 1.255 0 0 1-1.256-1.255v-1.251l-.061.117a4.7 4.7 0 0 1-1.782 1.884 4.77 4.77 0 0 1-2.485.67 5.6 5.6 0 0 1-1.485-.188l.009 2.764a1.255 1.255 0 0 1-1.255 1.259h-1.729a1.255 1.255 0 0 1-1.255-1.255v-3.537a1.255 1.255 0 0 1-1.167.793h-1.679a1.25 1.25 0 0 1-.77-.263 4.5 4.5 0 0 1-1.945.429c-.885 0-1.724-.21-2.495-.632l-.017-.01a5 5 0 0 1-1.081-.836 1.255 1.255 0 0 1-1.254 1.312h-1.81a1.255 1.255 0 0 1-1.228-.99l-.782-3.625-2.044 3.939a1.25 1.25 0 0 1-1.115.676h-.098a1.25 1.25 0 0 1-1.116-.68l-2.061-3.994zM35.92 16.63l.207-.114.223-.15q.493-.356.735-.785l.061-.118.033 1.332h1.678V9.242h-1.694l-.033 1.267q-.133-.329-.526-.658l-.032-.028a3.2 3.2 0 0 0-.668-.428l-.27-.12a3.3 3.3 0 0 0-1.235-.23q-1.136-.001-1.974.493a3.36 3.36 0 0 0-1.3 1.382q-.445.89-.444 2.074 0 1.2.51 2.107a3.8 3.8 0 0 0 1.382 1.381 3.9 3.9 0 0 0 1.893.477q.795 0 1.455-.33zm-2.789-5.38q-.576.675-.575 1.762 0 1.102.559 1.794.576.675 1.645.675a2.25 2.25 0 0 0 .934-.19 2.2 2.2 0 0 0 .468-.29l.178-.161a2.2 2.2 0 0 0 .397-.561q.244-.5.244-1.15v-.115q0-.708-.296-1.267l-.043-.077a2.2 2.2 0 0 0-.633-.709l-.13-.086-.047-.028a2.1 2.1 0 0 0-1.073-.285q-1.052 0-1.629.692zm2.316 2.706c.163-.17.28-.407.28-.83v-.114c0-.292-.06-.508-.15-.68a.96.96 0 0 0-.353-.389.85.85 0 0 0-.464-.127c-.4 0-.56.114-.664.239l-.01.012c-.148.174-.275.45-.275.945 0 .506.122.801.27.99.097.11.266.224.68.224.303 0 .504-.09.687-.269zm7.545 1.705a2.6 2.6 0 0 0 .331.423q.319.33.755.548l.173.074q.65.255 1.49.255 1.02 0 1.844-.493a3.45 3.45 0 0 0 1.316-1.4q.493-.904.493-2.089 0-1.909-.988-2.913-.988-1.02-2.584-1.02-.898 0-1.575.347a3 3 0 0 0-.415.262l-.199.166a3.4 3.4 0 0 0-.64.82V9.242h-1.712v11.553h1.729l-.017-5.134zm.53-1.138q.206.29.48.5l.155.11.053.034q.51.296 1.119.297 1.07 0 1.645-.675.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.435 0-.835.16a2 2 0 0 0-.284.136 2 2 0 0 0-.363.254 2.2 2.2 0 0 0-.46.569l-.082.162a2.6 2.6 0 0 0-.213 1.072v.115q0 .707.296 1.267l.135.211zm.964-.818a1.1 1.1 0 0 0 .367.385.94.94 0 0 0 .476.118c.423 0 .59-.117.687-.23.159-.194.28-.478.28-.95 0-.53-.133-.8-.266-.952l-.021-.025c-.078-.094-.231-.221-.68-.221a1 1 0 0 0-.503.135l-.012.007a.86.86 0 0 0-.335.343c-.073.133-.132.324-.132.614v.115a1.4 1.4 0 0 0 .14.66zm15.7-6.222q.347-.346.346-.856a1.05 1.05 0 0 0-.345-.79 1.18 1.18 0 0 0-.84-.329q-.51 0-.855.33a1.05 1.05 0 0 0-.346.79q0 .51.346.855.345.346.856.346.51 0 .839-.346zm4.337 9.314.033-1.332q.191.403.59.747l.098.081a4 4 0 0 0 .316.224l.223.122a3.2 3.2 0 0 0 1.44.322 3.8 3.8 0 0 0 1.875-.477 3.5 3.5 0 0 0 1.382-1.366q.527-.89.526-2.09 0-1.184-.444-2.073a3.24 3.24 0 0 0-1.283-1.399q-.823-.51-1.942-.51a3.5 3.5 0 0 0-1.527.344l-.086.043-.165.09a3 3 0 0 0-.33.214q-.432.315-.656.707a2 2 0 0 0-.099.198l.082-1.283V4.701h-1.744v12.095zm.473-2.509a2.5 2.5 0 0 0 .566.7q.117.098.245.18l.144.08a2.1 2.1 0 0 0 .975.232q1.07 0 1.645-.675.576-.69.576-1.778 0-1.102-.576-1.777-.56-.691-1.645-.692a2.2 2.2 0 0 0-1.015.235q-.22.113-.415.282l-.15.142a2.1 2.1 0 0 0-.42.594q-.223.479-.223 1.1v.115q0 .705.293 1.26zm2.616-.293c.157-.191.28-.479.28-.967 0-.51-.13-.79-.276-.961l-.021-.026c-.082-.1-.232-.225-.67-.225a.87.87 0 0 0-.681.279l-.012.011c-.154.155-.274.38-.274.807v.115c0 .285.057.499.144.669a1.1 1.1 0 0 0 .367.405c.137.082.28.123.455.123.423 0 .59-.118.686-.23zm8.266-3.013q.345-.13.724-.14l.069-.002q.493 0 .642.099l.247-1.794q-.196-.099-.717-.099a2.3 2.3 0 0 0-.545.063 2 2 0 0 0-.411.148 2.2 2.2 0 0 0-.4.249 2.5 2.5 0 0 0-.485.499 2.7 2.7 0 0 0-.32.581l-.05.137v-1.48h-1.778v7.553h1.777v-3.884q0-.546.159-.943a1.5 1.5 0 0 1 .466-.636 2.5 2.5 0 0 1 .399-.253 2 2 0 0 1 .224-.099zm9.784 2.656.05-.922q0-1.743-.856-2.698-.838-.97-2.584-.97-1.119-.001-2.007.493a3.46 3.46 0 0 0-1.4 1.382q-.493.906-.493 2.106 0 1.07.428 1.975.428.89 1.332 1.432.906.526 2.255.526.973 0 1.668-.185l.044-.012.135-.04q.613-.184.984-.421l-.542-1.267q-.3.162-.642.274l-.297.087q-.51.131-1.3.131-.954 0-1.497-.444a1.6 1.6 0 0 1-.192-.193q-.366-.44-.512-1.234l-.004-.021zm-5.427-1.256-.003.022h3.752v-.138q-.011-.727-.288-1.118a1 1 0 0 0-.156-.176q-.46-.428-1.316-.428-.986 0-1.494.604-.379.45-.494 1.234zm-27.053 2.77V4.7h-1.86v12.095h5.333V15.15zm7.103-5.908v7.553h-1.843V9.242h1.843z'/%3E%3Cpath fill='%23fff' d='m19.63 11.151-.757-1.71-.345 1.71-1.12 5.644h-1.827L18.083 4.7h.197l3.325 6.533.988 2.19.988-2.19L26.839 4.7h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.93 5.644h-.098l-2.913-5.644zm14.836 5.81q-1.02 0-1.893-.478a3.8 3.8 0 0 1-1.381-1.382q-.51-.906-.51-2.106 0-1.185.444-2.074a3.36 3.36 0 0 1 1.3-1.382q.839-.494 1.974-.494a3.3 3.3 0 0 1 1.234.231 3.3 3.3 0 0 1 .97.575q.396.33.527.659l.033-1.267h1.694v7.553H37.18l-.033-1.332q-.279.593-1.02 1.053a3.17 3.17 0 0 1-1.662.444zm.296-1.482q.938 0 1.58-.642.642-.66.642-1.711v-.115q0-.708-.296-1.267a2.2 2.2 0 0 0-.807-.872 2.1 2.1 0 0 0-1.119-.313q-1.053 0-1.629.692-.575.675-.575 1.76 0 1.103.559 1.795.577.675 1.645.675zm6.521-6.237h1.711v1.4q.906-1.597 2.83-1.597 1.596 0 2.584 1.02.988 1.005.988 2.914 0 1.185-.493 2.09a3.46 3.46 0 0 1-1.316 1.399 3.5 3.5 0 0 1-1.844.493q-.954 0-1.662-.329a2.67 2.67 0 0 1-1.086-.97l.017 5.134h-1.728zm4.048 6.22q1.07 0 1.645-.674.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.592 0-1.12.296-.51.28-.822.823-.296.527-.296 1.234v.115q0 .708.296 1.267.313.543.823.855.51.296 1.119.297z'/%3E%3Cpath fill='%23e1e3e9' d='M51.325 4.7h1.86v10.45h3.473v1.646h-5.333zm7.12 4.542h1.843v7.553h-1.843zm.905-1.415a1.16 1.16 0 0 1-.856-.346 1.17 1.17 0 0 1-.346-.856 1.05 1.05 0 0 1 .346-.79q.346-.329.856-.329.494 0 .839.33a1.05 1.05 0 0 1 .345.79 1.16 1.16 0 0 1-.345.855q-.33.346-.84.346zm7.875 9.133a3.17 3.17 0 0 1-1.662-.444q-.723-.46-1.004-1.053l-.033 1.332h-1.71V4.701h1.743v4.657l-.082 1.283q.279-.658 1.086-1.119a3.5 3.5 0 0 1 1.778-.477q1.119 0 1.942.51a3.24 3.24 0 0 1 1.283 1.4q.445.888.444 2.072 0 1.201-.526 2.09a3.5 3.5 0 0 1-1.382 1.366 3.8 3.8 0 0 1-1.876.477zm-.296-1.481q1.069 0 1.645-.675.577-.69.577-1.778 0-1.102-.577-1.776-.56-.691-1.645-.692a2.12 2.12 0 0 0-1.58.659q-.642.641-.642 1.694v.115q0 .71.296 1.267a2.4 2.4 0 0 0 .807.872 2.1 2.1 0 0 0 1.119.313zm5.927-6.237h1.777v1.481q.263-.757.856-1.217a2.14 2.14 0 0 1 1.349-.46q.527 0 .724.098l-.247 1.794q-.149-.099-.642-.099-.774 0-1.416.494-.626.493-.626 1.58v3.883h-1.777V9.242zm9.534 7.718q-1.35 0-2.255-.526-.904-.543-1.332-1.432a4.6 4.6 0 0 1-.428-1.975q0-1.2.493-2.106a3.46 3.46 0 0 1 1.4-1.382q.889-.495 2.007-.494 1.744 0 2.584.97.855.956.856 2.7 0 .444-.05.92h-5.43q.18 1.005.708 1.45.542.443 1.497.443.79 0 1.3-.131a4 4 0 0 0 .938-.362l.542 1.267q-.411.263-1.119.46-.708.198-1.711.197zm1.596-4.558q.016-1.02-.444-1.432-.46-.428-1.316-.428-1.728 0-1.991 1.86z'/%3E%3Cpath d='M5.074 15.948a.484.657 0 0 0-.486.659v1.84a.484.657 0 0 0 .486.659h4.101a.484.657 0 0 0 .486-.659v-1.84a.484.657 0 0 0-.486-.659zm3.56 1.16H5.617v.838h3.017z' style='fill:%23fff;fill-rule:evenodd;stroke-width:1.03600001'/%3E%3Cg style='stroke-width:1.12603545'%3E%3Cpath d='M-9.408-1.416c-3.833-.025-7.056 2.912-7.08 6.615-.02 3.08 1.653 4.832 3.107 6.268.903.892 1.721 1.74 2.32 2.902l-.525-.004c-.543-.003-.992.304-1.24.639a1.87 1.87 0 0 0-.362 1.121l-.011 1.877c-.003.402.104.787.347 1.125.244.338.688.653 1.23.656l4.142.028c.542.003.99-.306 1.238-.641a1.87 1.87 0 0 0 .363-1.121l.012-1.875a1.87 1.87 0 0 0-.348-1.127c-.243-.338-.688-.653-1.23-.656l-.518-.004c.597-1.145 1.425-1.983 2.348-2.87 1.473-1.414 3.18-3.149 3.2-6.226-.016-3.59-2.923-6.684-6.993-6.707m-.006 1.1v.002c3.274.02 5.92 2.532 5.9 5.6-.017 2.706-1.39 4.026-2.863 5.44-1.034.994-2.118 2.033-2.814 3.633-.018.041-.052.055-.075.065q-.013.004-.02.01a.34.34 0 0 1-.226.084.34.34 0 0 1-.224-.086l-.092-.077c-.699-1.615-1.768-2.669-2.781-3.67-1.454-1.435-2.797-2.762-2.78-5.478.02-3.067 2.7-5.545 5.975-5.523m-.02 2.826c-1.62-.01-2.944 1.315-2.955 2.96-.01 1.646 1.295 2.988 2.916 2.999h.002c1.621.01 2.943-1.316 2.953-2.961.011-1.646-1.294-2.988-2.916-2.998m-.005 1.1c1.017.006 1.829.83 1.822 1.89s-.83 1.874-1.848 1.867c-1.018-.006-1.829-.83-1.822-1.89s.83-1.874 1.848-1.868m-2.155 11.857 4.14.025c.271.002.49.305.487.676l-.013 1.875c-.003.37-.224.67-.495.668l-4.14-.025c-.27-.002-.487-.306-.485-.676l.012-1.875c.003-.37.224-.67.494-.668' style='color:%23000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:%23000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:evenodd;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:%23000;solid-opacity:1;vector-effect:none;fill:%23000;fill-opacity:.4;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-9.415-.316C-12.69-.338-15.37 2.14-15.39 5.207c-.017 2.716 1.326 4.041 2.78 5.477 1.013 1 2.081 2.055 2.78 3.67l.092.076a.34.34 0 0 0 .225.086.34.34 0 0 0 .227-.083l.019-.01c.022-.009.057-.024.074-.064.697-1.6 1.78-2.64 2.814-3.634 1.473-1.414 2.847-2.733 2.864-5.44.02-3.067-2.627-5.58-5.901-5.601m-.057 8.784c1.621.011 2.944-1.315 2.955-2.96.01-1.646-1.295-2.988-2.916-2.999-1.622-.01-2.945 1.315-2.955 2.96s1.295 2.989 2.916 3' style='clip-rule:evenodd;fill:%23e1e3e9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-11.594 15.465c-.27-.002-.492.297-.494.668l-.012 1.876c-.003.371.214.673.485.675l4.14.027c.271.002.492-.298.495-.668l.012-1.877c.003-.37-.215-.672-.485-.674z' style='clip-rule:evenodd;fill:%23fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3C/g%3E%3C/svg%3E")}}@media (forced-colors:active) and (prefers-color-scheme:light){a.maplibregl-ctrl-logo{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='88' height='23' fill='none'%3E%3Cpath fill='%23000' fill-opacity='.4' fill-rule='evenodd' d='M17.408 16.796h-1.827l2.501-12.095h.198l3.324 6.533.988 2.19.988-2.19 3.258-6.533h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.929 5.644h-.098l-2.914-5.644-.757-1.71-.345 1.71zm1.958-3.42-.726 3.663a1.255 1.255 0 0 1-1.232 1.011h-1.827a1.255 1.255 0 0 1-1.229-1.509l2.501-12.095a1.255 1.255 0 0 1 1.23-1.001h.197a1.25 1.25 0 0 1 1.12.685l3.19 6.273 3.125-6.263a1.25 1.25 0 0 1 1.123-.695h.181a1.255 1.255 0 0 1 1.227.991l1.443 6.71a5 5 0 0 1 .314-.787l.009-.016a4.6 4.6 0 0 1 1.777-1.887c.782-.46 1.668-.667 2.611-.667a4.6 4.6 0 0 1 1.7.32l.306.134c.21-.16.474-.256.759-.256h1.694a1.255 1.255 0 0 1 1.212.925 1.255 1.255 0 0 1 1.212-.925h1.711c.284 0 .545.094.755.252.613-.3 1.312-.45 2.075-.45 1.356 0 2.557.445 3.482 1.4q.47.48.763 1.064V4.701a1.255 1.255 0 0 1 1.255-1.255h1.86A1.255 1.255 0 0 1 54.44 4.7v9.194h2.217c.19 0 .37.043.532.118v-4.77c0-.356.147-.678.385-.906a2.42 2.42 0 0 1-.682-1.71c0-.665.267-1.253.735-1.7a2.45 2.45 0 0 1 1.722-.674 2.43 2.43 0 0 1 1.705.675q.318.302.504.683V4.7a1.255 1.255 0 0 1 1.255-1.255h1.744A1.255 1.255 0 0 1 65.812 4.7v3.335a4.8 4.8 0 0 1 1.526-.246c.938 0 1.817.214 2.59.69a4.47 4.47 0 0 1 1.67 1.743v-.98a1.255 1.255 0 0 1 1.256-1.256h1.777c.233 0 .451.064.639.174a3.4 3.4 0 0 1 1.567-.372c.346 0 .861.02 1.285.232a1.25 1.25 0 0 1 .689 1.004 4.7 4.7 0 0 1 .853-.588c.795-.44 1.675-.647 2.61-.647 1.385 0 2.65.39 3.525 1.396.836.938 1.168 2.173 1.168 3.528q-.001.515-.056 1.051a1.255 1.255 0 0 1-.947 1.09l.408.952a1.255 1.255 0 0 1-.477 1.552c-.418.268-.92.463-1.458.612-.613.171-1.304.244-2.049.244-1.06 0-2.043-.207-2.886-.698l-.015-.008c-.798-.48-1.419-1.135-1.818-1.963l-.004-.008a5.8 5.8 0 0 1-.548-2.512q0-.429.053-.843a1.3 1.3 0 0 1-.333-.086l-.166-.004c-.223 0-.426.062-.643.228-.03.024-.142.139-.142.59v3.883a1.255 1.255 0 0 1-1.256 1.256h-1.777a1.255 1.255 0 0 1-1.256-1.256V15.69l-.032.057a4.8 4.8 0 0 1-1.86 1.833 5.04 5.04 0 0 1-2.484.634 4.5 4.5 0 0 1-1.935-.424 1.25 1.25 0 0 1-.764.258h-1.71a1.255 1.255 0 0 1-1.256-1.255V7.687a2.4 2.4 0 0 1-.428.625c.253.23.412.561.412.93v7.553a1.255 1.255 0 0 1-1.256 1.255h-1.843a1.25 1.25 0 0 1-.894-.373c-.228.23-.544.373-.894.373H51.32a1.255 1.255 0 0 1-1.256-1.255v-1.251l-.061.117a4.7 4.7 0 0 1-1.782 1.884 4.77 4.77 0 0 1-2.485.67 5.6 5.6 0 0 1-1.485-.188l.009 2.764a1.255 1.255 0 0 1-1.255 1.259h-1.729a1.255 1.255 0 0 1-1.255-1.255v-3.537a1.255 1.255 0 0 1-1.167.793h-1.679a1.25 1.25 0 0 1-.77-.263 4.5 4.5 0 0 1-1.945.429c-.885 0-1.724-.21-2.495-.632l-.017-.01a5 5 0 0 1-1.081-.836 1.255 1.255 0 0 1-1.254 1.312h-1.81a1.255 1.255 0 0 1-1.228-.99l-.782-3.625-2.044 3.939a1.25 1.25 0 0 1-1.115.676h-.098a1.25 1.25 0 0 1-1.116-.68l-2.061-3.994zM35.92 16.63l.207-.114.223-.15q.493-.356.735-.785l.061-.118.033 1.332h1.678V9.242h-1.694l-.033 1.267q-.133-.329-.526-.658l-.032-.028a3.2 3.2 0 0 0-.668-.428l-.27-.12a3.3 3.3 0 0 0-1.235-.23q-1.136-.001-1.974.493a3.36 3.36 0 0 0-1.3 1.382q-.445.89-.444 2.074 0 1.2.51 2.107a3.8 3.8 0 0 0 1.382 1.381 3.9 3.9 0 0 0 1.893.477q.795 0 1.455-.33zm-2.789-5.38q-.576.675-.575 1.762 0 1.102.559 1.794.576.675 1.645.675a2.25 2.25 0 0 0 .934-.19 2.2 2.2 0 0 0 .468-.29l.178-.161a2.2 2.2 0 0 0 .397-.561q.244-.5.244-1.15v-.115q0-.708-.296-1.267l-.043-.077a2.2 2.2 0 0 0-.633-.709l-.13-.086-.047-.028a2.1 2.1 0 0 0-1.073-.285q-1.052 0-1.629.692zm2.316 2.706c.163-.17.28-.407.28-.83v-.114c0-.292-.06-.508-.15-.68a.96.96 0 0 0-.353-.389.85.85 0 0 0-.464-.127c-.4 0-.56.114-.664.239l-.01.012c-.148.174-.275.45-.275.945 0 .506.122.801.27.99.097.11.266.224.68.224.303 0 .504-.09.687-.269zm7.545 1.705a2.6 2.6 0 0 0 .331.423q.319.33.755.548l.173.074q.65.255 1.49.255 1.02 0 1.844-.493a3.45 3.45 0 0 0 1.316-1.4q.493-.904.493-2.089 0-1.909-.988-2.913-.988-1.02-2.584-1.02-.898 0-1.575.347a3 3 0 0 0-.415.262l-.199.166a3.4 3.4 0 0 0-.64.82V9.242h-1.712v11.553h1.729l-.017-5.134zm.53-1.138q.206.29.48.5l.155.11.053.034q.51.296 1.119.297 1.07 0 1.645-.675.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.435 0-.835.16a2 2 0 0 0-.284.136 2 2 0 0 0-.363.254 2.2 2.2 0 0 0-.46.569l-.082.162a2.6 2.6 0 0 0-.213 1.072v.115q0 .707.296 1.267l.135.211zm.964-.818a1.1 1.1 0 0 0 .367.385.94.94 0 0 0 .476.118c.423 0 .59-.117.687-.23.159-.194.28-.478.28-.95 0-.53-.133-.8-.266-.952l-.021-.025c-.078-.094-.231-.221-.68-.221a1 1 0 0 0-.503.135l-.012.007a.86.86 0 0 0-.335.343c-.073.133-.132.324-.132.614v.115a1.4 1.4 0 0 0 .14.66zm15.7-6.222q.347-.346.346-.856a1.05 1.05 0 0 0-.345-.79 1.18 1.18 0 0 0-.84-.329q-.51 0-.855.33a1.05 1.05 0 0 0-.346.79q0 .51.346.855.345.346.856.346.51 0 .839-.346zm4.337 9.314.033-1.332q.191.403.59.747l.098.081a4 4 0 0 0 .316.224l.223.122a3.2 3.2 0 0 0 1.44.322 3.8 3.8 0 0 0 1.875-.477 3.5 3.5 0 0 0 1.382-1.366q.527-.89.526-2.09 0-1.184-.444-2.073a3.24 3.24 0 0 0-1.283-1.399q-.823-.51-1.942-.51a3.5 3.5 0 0 0-1.527.344l-.086.043-.165.09a3 3 0 0 0-.33.214q-.432.315-.656.707a2 2 0 0 0-.099.198l.082-1.283V4.701h-1.744v12.095zm.473-2.509a2.5 2.5 0 0 0 .566.7q.117.098.245.18l.144.08a2.1 2.1 0 0 0 .975.232q1.07 0 1.645-.675.576-.69.576-1.778 0-1.102-.576-1.777-.56-.691-1.645-.692a2.2 2.2 0 0 0-1.015.235q-.22.113-.415.282l-.15.142a2.1 2.1 0 0 0-.42.594q-.223.479-.223 1.1v.115q0 .705.293 1.26zm2.616-.293c.157-.191.28-.479.28-.967 0-.51-.13-.79-.276-.961l-.021-.026c-.082-.1-.232-.225-.67-.225a.87.87 0 0 0-.681.279l-.012.011c-.154.155-.274.38-.274.807v.115c0 .285.057.499.144.669a1.1 1.1 0 0 0 .367.405c.137.082.28.123.455.123.423 0 .59-.118.686-.23zm8.266-3.013q.345-.13.724-.14l.069-.002q.493 0 .642.099l.247-1.794q-.196-.099-.717-.099a2.3 2.3 0 0 0-.545.063 2 2 0 0 0-.411.148 2.2 2.2 0 0 0-.4.249 2.5 2.5 0 0 0-.485.499 2.7 2.7 0 0 0-.32.581l-.05.137v-1.48h-1.778v7.553h1.777v-3.884q0-.546.159-.943a1.5 1.5 0 0 1 .466-.636 2.5 2.5 0 0 1 .399-.253 2 2 0 0 1 .224-.099zm9.784 2.656.05-.922q0-1.743-.856-2.698-.838-.97-2.584-.97-1.119-.001-2.007.493a3.46 3.46 0 0 0-1.4 1.382q-.493.906-.493 2.106 0 1.07.428 1.975.428.89 1.332 1.432.906.526 2.255.526.973 0 1.668-.185l.044-.012.135-.04q.613-.184.984-.421l-.542-1.267q-.3.162-.642.274l-.297.087q-.51.131-1.3.131-.954 0-1.497-.444a1.6 1.6 0 0 1-.192-.193q-.366-.44-.512-1.234l-.004-.021zm-5.427-1.256-.003.022h3.752v-.138q-.011-.727-.288-1.118a1 1 0 0 0-.156-.176q-.46-.428-1.316-.428-.986 0-1.494.604-.379.45-.494 1.234zm-27.053 2.77V4.7h-1.86v12.095h5.333V15.15zm7.103-5.908v7.553h-1.843V9.242h1.843z'/%3E%3Cpath fill='%23fff' d='m19.63 11.151-.757-1.71-.345 1.71-1.12 5.644h-1.827L18.083 4.7h.197l3.325 6.533.988 2.19.988-2.19L26.839 4.7h.181l2.6 12.095h-1.81l-1.218-5.644-.362-1.71-.658 1.71-2.93 5.644h-.098l-2.913-5.644zm14.836 5.81q-1.02 0-1.893-.478a3.8 3.8 0 0 1-1.381-1.382q-.51-.906-.51-2.106 0-1.185.444-2.074a3.36 3.36 0 0 1 1.3-1.382q.839-.494 1.974-.494a3.3 3.3 0 0 1 1.234.231 3.3 3.3 0 0 1 .97.575q.396.33.527.659l.033-1.267h1.694v7.553H37.18l-.033-1.332q-.279.593-1.02 1.053a3.17 3.17 0 0 1-1.662.444zm.296-1.482q.938 0 1.58-.642.642-.66.642-1.711v-.115q0-.708-.296-1.267a2.2 2.2 0 0 0-.807-.872 2.1 2.1 0 0 0-1.119-.313q-1.053 0-1.629.692-.575.675-.575 1.76 0 1.103.559 1.795.577.675 1.645.675zm6.521-6.237h1.711v1.4q.906-1.597 2.83-1.597 1.596 0 2.584 1.02.988 1.005.988 2.914 0 1.185-.493 2.09a3.46 3.46 0 0 1-1.316 1.399 3.5 3.5 0 0 1-1.844.493q-.954 0-1.662-.329a2.67 2.67 0 0 1-1.086-.97l.017 5.134h-1.728zm4.048 6.22q1.07 0 1.645-.674.577-.69.576-1.762 0-1.119-.576-1.777-.558-.675-1.645-.675-.592 0-1.12.296-.51.28-.822.823-.296.527-.296 1.234v.115q0 .708.296 1.267.313.543.823.855.51.296 1.119.297z'/%3E%3Cpath fill='%23e1e3e9' d='M51.325 4.7h1.86v10.45h3.473v1.646h-5.333zm7.12 4.542h1.843v7.553h-1.843zm.905-1.415a1.16 1.16 0 0 1-.856-.346 1.17 1.17 0 0 1-.346-.856 1.05 1.05 0 0 1 .346-.79q.346-.329.856-.329.494 0 .839.33a1.05 1.05 0 0 1 .345.79 1.16 1.16 0 0 1-.345.855q-.33.346-.84.346zm7.875 9.133a3.17 3.17 0 0 1-1.662-.444q-.723-.46-1.004-1.053l-.033 1.332h-1.71V4.701h1.743v4.657l-.082 1.283q.279-.658 1.086-1.119a3.5 3.5 0 0 1 1.778-.477q1.119 0 1.942.51a3.24 3.24 0 0 1 1.283 1.4q.445.888.444 2.072 0 1.201-.526 2.09a3.5 3.5 0 0 1-1.382 1.366 3.8 3.8 0 0 1-1.876.477zm-.296-1.481q1.069 0 1.645-.675.577-.69.577-1.778 0-1.102-.577-1.776-.56-.691-1.645-.692a2.12 2.12 0 0 0-1.58.659q-.642.641-.642 1.694v.115q0 .71.296 1.267a2.4 2.4 0 0 0 .807.872 2.1 2.1 0 0 0 1.119.313zm5.927-6.237h1.777v1.481q.263-.757.856-1.217a2.14 2.14 0 0 1 1.349-.46q.527 0 .724.098l-.247 1.794q-.149-.099-.642-.099-.774 0-1.416.494-.626.493-.626 1.58v3.883h-1.777V9.242zm9.534 7.718q-1.35 0-2.255-.526-.904-.543-1.332-1.432a4.6 4.6 0 0 1-.428-1.975q0-1.2.493-2.106a3.46 3.46 0 0 1 1.4-1.382q.889-.495 2.007-.494 1.744 0 2.584.97.855.956.856 2.7 0 .444-.05.92h-5.43q.18 1.005.708 1.45.542.443 1.497.443.79 0 1.3-.131a4 4 0 0 0 .938-.362l.542 1.267q-.411.263-1.119.46-.708.198-1.711.197zm1.596-4.558q.016-1.02-.444-1.432-.46-.428-1.316-.428-1.728 0-1.991 1.86z'/%3E%3Cpath d='M5.074 15.948a.484.657 0 0 0-.486.659v1.84a.484.657 0 0 0 .486.659h4.101a.484.657 0 0 0 .486-.659v-1.84a.484.657 0 0 0-.486-.659zm3.56 1.16H5.617v.838h3.017z' style='fill:%23fff;fill-rule:evenodd;stroke-width:1.03600001'/%3E%3Cg style='stroke-width:1.12603545'%3E%3Cpath d='M-9.408-1.416c-3.833-.025-7.056 2.912-7.08 6.615-.02 3.08 1.653 4.832 3.107 6.268.903.892 1.721 1.74 2.32 2.902l-.525-.004c-.543-.003-.992.304-1.24.639a1.87 1.87 0 0 0-.362 1.121l-.011 1.877c-.003.402.104.787.347 1.125.244.338.688.653 1.23.656l4.142.028c.542.003.99-.306 1.238-.641a1.87 1.87 0 0 0 .363-1.121l.012-1.875a1.87 1.87 0 0 0-.348-1.127c-.243-.338-.688-.653-1.23-.656l-.518-.004c.597-1.145 1.425-1.983 2.348-2.87 1.473-1.414 3.18-3.149 3.2-6.226-.016-3.59-2.923-6.684-6.993-6.707m-.006 1.1v.002c3.274.02 5.92 2.532 5.9 5.6-.017 2.706-1.39 4.026-2.863 5.44-1.034.994-2.118 2.033-2.814 3.633-.018.041-.052.055-.075.065q-.013.004-.02.01a.34.34 0 0 1-.226.084.34.34 0 0 1-.224-.086l-.092-.077c-.699-1.615-1.768-2.669-2.781-3.67-1.454-1.435-2.797-2.762-2.78-5.478.02-3.067 2.7-5.545 5.975-5.523m-.02 2.826c-1.62-.01-2.944 1.315-2.955 2.96-.01 1.646 1.295 2.988 2.916 2.999h.002c1.621.01 2.943-1.316 2.953-2.961.011-1.646-1.294-2.988-2.916-2.998m-.005 1.1c1.017.006 1.829.83 1.822 1.89s-.83 1.874-1.848 1.867c-1.018-.006-1.829-.83-1.822-1.89s.83-1.874 1.848-1.868m-2.155 11.857 4.14.025c.271.002.49.305.487.676l-.013 1.875c-.003.37-.224.67-.495.668l-4.14-.025c-.27-.002-.487-.306-.485-.676l.012-1.875c.003-.37.224-.67.494-.668' style='color:%23000;font-style:normal;font-variant:normal;font-weight:400;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:%23000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:evenodd;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:%23000;solid-opacity:1;vector-effect:none;fill:%23000;fill-opacity:.4;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-9.415-.316C-12.69-.338-15.37 2.14-15.39 5.207c-.017 2.716 1.326 4.041 2.78 5.477 1.013 1 2.081 2.055 2.78 3.67l.092.076a.34.34 0 0 0 .225.086.34.34 0 0 0 .227-.083l.019-.01c.022-.009.057-.024.074-.064.697-1.6 1.78-2.64 2.814-3.634 1.473-1.414 2.847-2.733 2.864-5.44.02-3.067-2.627-5.58-5.901-5.601m-.057 8.784c1.621.011 2.944-1.315 2.955-2.96.01-1.646-1.295-2.988-2.916-2.999-1.622-.01-2.945 1.315-2.955 2.96s1.295 2.989 2.916 3' style='clip-rule:evenodd;fill:%23e1e3e9;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3Cpath d='M-11.594 15.465c-.27-.002-.492.297-.494.668l-.012 1.876c-.003.371.214.673.485.675l4.14.027c.271.002.492-.298.495-.668l.012-1.877c.003-.37-.215-.672-.485-.674z' style='clip-rule:evenodd;fill:%23fff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2.47727823;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:.4' transform='translate(15.553 2.85)scale(.88807)'/%3E%3C/g%3E%3C/svg%3E")}}.maplibregl-ctrl.maplibregl-ctrl-attrib{background-color:hsla(0,0%,100%,.5);margin:0;padding:0 5px}@media screen{.maplibregl-ctrl-attrib.maplibregl-compact{background-color:#fff;border-radius:12px;box-sizing:content-box;color:#000;margin:10px;min-height:20px;padding:2px 24px 2px 0;position:relative}.maplibregl-ctrl-attrib.maplibregl-compact-show{padding:2px 28px 2px 8px;visibility:visible}.maplibregl-ctrl-bottom-left>.maplibregl-ctrl-attrib.maplibregl-compact-show,.maplibregl-ctrl-top-left>.maplibregl-ctrl-attrib.maplibregl-compact-show{border-radius:12px;padding:2px 8px 2px 28px}.maplibregl-ctrl-attrib.maplibregl-compact .maplibregl-ctrl-attrib-inner{display:none}.maplibregl-ctrl-attrib-button{background-color:hsla(0,0%,100%,.5);background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill-rule='evenodd' viewBox='0 0 20 20'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E");border:0;border-radius:12px;box-sizing:border-box;cursor:pointer;display:none;height:24px;outline:none;position:absolute;right:0;top:0;width:24px}.maplibregl-ctrl-attrib summary.maplibregl-ctrl-attrib-button{-webkit-appearance:none;-moz-appearance:none;appearance:none;list-style:none}.maplibregl-ctrl-attrib summary.maplibregl-ctrl-attrib-button::-webkit-details-marker{display:none}.maplibregl-ctrl-bottom-left .maplibregl-ctrl-attrib-button,.maplibregl-ctrl-top-left .maplibregl-ctrl-attrib-button{left:0}.maplibregl-ctrl-attrib.maplibregl-compact .maplibregl-ctrl-attrib-button,.maplibregl-ctrl-attrib.maplibregl-compact-show .maplibregl-ctrl-attrib-inner{display:block}.maplibregl-ctrl-attrib.maplibregl-compact-show .maplibregl-ctrl-attrib-button{background-color:rgb(0 0 0/5%)}.maplibregl-ctrl-bottom-right>.maplibregl-ctrl-attrib.maplibregl-compact:after{bottom:0;right:0}.maplibregl-ctrl-top-right>.maplibregl-ctrl-attrib.maplibregl-compact:after{right:0;top:0}.maplibregl-ctrl-top-left>.maplibregl-ctrl-attrib.maplibregl-compact:after{left:0;top:0}.maplibregl-ctrl-bottom-left>.maplibregl-ctrl-attrib.maplibregl-compact:after{bottom:0;left:0}}@media screen and (forced-colors:active){.maplibregl-ctrl-attrib.maplibregl-compact:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='%23fff' fill-rule='evenodd' viewBox='0 0 20 20'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E")}}@media screen and (forced-colors:active) and (prefers-color-scheme:light){.maplibregl-ctrl-attrib.maplibregl-compact:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill-rule='evenodd' viewBox='0 0 20 20'%3E%3Cpath d='M4 10a6 6 0 1 0 12 0 6 6 0 1 0-12 0m5-3a1 1 0 1 0 2 0 1 1 0 1 0-2 0m0 3a1 1 0 1 1 2 0v3a1 1 0 1 1-2 0'/%3E%3C/svg%3E")}}.maplibregl-ctrl-attrib a{color:rgba(0,0,0,.75);text-decoration:none}.maplibregl-ctrl-attrib a:hover{color:inherit;text-decoration:underline}.maplibregl-attrib-empty{display:none}.maplibregl-ctrl-scale{background-color:hsla(0,0%,100%,.75);border:2px solid #333;border-top:#333;box-sizing:border-box;color:#333;font-size:10px;padding:0 5px}.maplibregl-popup{display:flex;left:0;pointer-events:none;position:absolute;top:0;will-change:transform}.maplibregl-popup-anchor-top,.maplibregl-popup-anchor-top-left,.maplibregl-popup-anchor-top-right{flex-direction:column}.maplibregl-popup-anchor-bottom,.maplibregl-popup-anchor-bottom-left,.maplibregl-popup-anchor-bottom-right{flex-direction:column-reverse}.maplibregl-popup-anchor-left{flex-direction:row}.maplibregl-popup-anchor-right{flex-direction:row-reverse}.maplibregl-popup-tip{border:10px solid transparent;height:0;width:0;z-index:1}.maplibregl-popup-anchor-top .maplibregl-popup-tip{align-self:center;border-bottom-color:#fff;border-top:none}.maplibregl-popup-anchor-top-left .maplibregl-popup-tip{align-self:flex-start;border-bottom-color:#fff;border-left:none;border-top:none}.maplibregl-popup-anchor-top-right .maplibregl-popup-tip{align-self:flex-end;border-bottom-color:#fff;border-right:none;border-top:none}.maplibregl-popup-anchor-bottom .maplibregl-popup-tip{align-self:center;border-bottom:none;border-top-color:#fff}.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip{align-self:flex-start;border-bottom:none;border-left:none;border-top-color:#fff}.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip{align-self:flex-end;border-bottom:none;border-right:none;border-top-color:#fff}.maplibregl-popup-anchor-left .maplibregl-popup-tip{align-self:center;border-left:none;border-right-color:#fff}.maplibregl-popup-anchor-right .maplibregl-popup-tip{align-self:center;border-left-color:#fff;border-right:none}.maplibregl-popup-close-button{background-color:transparent;border:0;border-radius:0 3px 0 0;cursor:pointer;position:absolute;right:0;top:0}.maplibregl-popup-close-button:hover{background-color:rgb(0 0 0/5%)}.maplibregl-popup-content{background:#fff;border-radius:3px;box-shadow:0 1px 2px rgba(0,0,0,.1);padding:15px 10px;pointer-events:auto;position:relative}.maplibregl-popup-anchor-top-left .maplibregl-popup-content{border-top-left-radius:0}.maplibregl-popup-anchor-top-right .maplibregl-popup-content{border-top-right-radius:0}.maplibregl-popup-anchor-bottom-left .maplibregl-popup-content{border-bottom-left-radius:0}.maplibregl-popup-anchor-bottom-right .maplibregl-popup-content{border-bottom-right-radius:0}.maplibregl-popup-track-pointer{display:none}.maplibregl-popup-track-pointer *{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.maplibregl-map:hover .maplibregl-popup-track-pointer{display:flex}.maplibregl-map:active .maplibregl-popup-track-pointer{display:none}.maplibregl-marker{left:0;position:absolute;top:0;transition:opacity .2s;will-change:transform}.maplibregl-user-location-dot,.maplibregl-user-location-dot:before{background-color:#1da1f2;border-radius:50%;height:15px;width:15px}.maplibregl-user-location-dot:before{animation:maplibregl-user-location-dot-pulse 2s infinite;content:"";position:absolute}.maplibregl-user-location-dot:after{border:2px solid #fff;border-radius:50%;box-shadow:0 0 3px rgba(0,0,0,.35);box-sizing:border-box;content:"";height:19px;left:-2px;position:absolute;top:-2px;width:19px}@keyframes maplibregl-user-location-dot-pulse{0%{opacity:1;transform:scale(1)}70%{opacity:0;transform:scale(3)}to{opacity:0;transform:scale(1)}}.maplibregl-user-location-dot-stale{background-color:#aaa}.maplibregl-user-location-dot-stale:after{display:none}.maplibregl-user-location-accuracy-circle{background-color:#1da1f233;border-radius:100%;height:1px;width:1px}.maplibregl-crosshair,.maplibregl-crosshair .maplibregl-interactive,.maplibregl-crosshair .maplibregl-interactive:active{cursor:crosshair}.maplibregl-boxzoom{background:#fff;border:2px dotted #202020;height:0;left:0;opacity:.5;position:absolute;top:0;width:0}.maplibregl-cooperative-gesture-screen{align-items:center;background:rgba(0,0,0,.4);color:#fff;display:flex;font-size:1.4em;inset:0;justify-content:center;line-height:1.2;opacity:0;padding:1rem;pointer-events:none;position:absolute;transition:opacity 1s ease 1s;z-index:99999}.maplibregl-cooperative-gesture-screen.maplibregl-show{opacity:1;transition:opacity .05s}.maplibregl-cooperative-gesture-screen .maplibregl-mobile-message{display:none}@media (hover:none),(width <= 480px){.maplibregl-cooperative-gesture-screen .maplibregl-desktop-message{display:none}.maplibregl-cooperative-gesture-screen .maplibregl-mobile-message{display:block}}.maplibregl-pseudo-fullscreen{height:100%!important;left:0!important;position:fixed!important;top:0!important;width:100%!important;z-index:99999} ================================================ FILE: website/src/pages/index.jsx ================================================ import React from 'react'; import {Home} from '@vis.gl/docusaurus-website/components'; import useBaseUrl from '@docusaurus/useBaseUrl'; import styled from 'styled-components'; import Layout from '@theme/Layout'; const HeroExample = styled.div` background-image: url(images/hero.jpg); background-size: cover; background-position: center; height: 100%; `; const TextContainer = styled.div` max-width: 800px; padding: 64px 112px; width: 70%; font-size: 14px; h2 { font: bold 32px/48px; margin: 24px 0 16px; position: relative; } h3 { font: bold 16px/24px; margin: 16px 0 0; position: relative; } h3 > img { position: absolute; top: -4px; width: 36px; left: -48px; } hr { border: none; background: #e1e8f0; height: 1px; margin: 24px 0 0; width: 32px; height: 2px; } @media screen and (max-width: 768px) { max-width: 100%; width: 100%; padding: 48px 48px 48px 80px; } `; export default function IndexPage() { const baseUrl = useBaseUrl('/'); return (

react-map-gl makes using MapLibre GL JS and Mapbox GL JS in React applications easy.


React Integration

Use a MapLibre GL JS or Mapbox GL JS map as a fully controlled reactive component.

Extensible

Comes with additional React interfaces such as context and hooks to support custom components.

Part of vis.gl's Framework Suite

Use together with e.g. deck.gl to render performant and compelling 2D and 3D WebGL visualizations on top of your MapLibre GL JS and Mapbox GL JS based maps.

); } ================================================ FILE: website/src/styles.css ================================================ /** * Any CSS included here will be global. The classic template * bundles Infima by default. Infima is a CSS framework designed to * work well for content-centric websites. */ /* You can override the default Infima variables here. */ :root { --ifm-color-primary: #00ade6; --ifm-color-primary-dark: #009ccf; --ifm-color-primary-darker: #0093c4; --ifm-color-primary-darkest: #0079a1; --ifm-color-primary-light: #00befd; --ifm-color-primary-lighter: #0ac2ff; --ifm-color-primary-lightest: #2ccbff; --ifm-color-white: #FFFFFF; --ifm-color-gray-200: #F7FAFC; --ifm-color-gray-300: #ECF2F7; --ifm-color-gray-400: #E1E8F0; --ifm-color-gray-500: #CAD5E0; --ifm-color-gray-600: #9EAEC0; --ifm-color-gray-700: #6F8196; --ifm-color-gray-800: #485668; --ifm-color-gray-900: #2B3848; --ifm-color-black: #19202C --code-font-size: 95%; } main .container { position: relative; min-height: calc(100vh - var(--ifm-navbar-height)); } .markdown { position: relative; } .menu__link { line-height: 1.5; } .menu__list { padding-bottom: 0.5rem; } .docusaurus-highlight-code-line { background-color: rgba(0, 0, 0, 0.1); display: block; margin: 0 calc(-1 * var(--pre-padding)); padding: 0 var(--pre-padding); } html[data-theme='dark'] .docusaurus-highlight-code-line { background-color: rgba(0, 0, 0, 0.3); } .tooltip { position: absolute; padding: 4px; background: rgba(0, 0, 0, 0.8); color: #fff; max-width: 300px; font-size: 12px; line-height: 16px; z-index: 9; pointer-events: none; } .control-panel { font-size: 14px; line-height: 18px; width: 284px; background: #fff; box-shadow: 0 0 4px rgba(0, 0, 0, 0.15); margin: 24px; padding: 12px 24px; position: absolute; top: 0; right: 0; outline: none; cursor: auto; } .control-panel h3 { font-size: 1.2em; font-weight: 500; margin: 8px 0; } .control-panel a { display: inline; } .control-panel p { margin-bottom: 16px; } .control-panel .legend { display: inline-block; width: 12px; height: 12px; } .control-panel hr { margin: 12px -24px; } .control-panel .source-link { text-align: right; margin-top: 8px; } .control-panel .source-link a { font-weight: bold; color: #486865; font-size: 11px; } .control-panel .input { position: relative; display: flex; width: 100%; } .control-panel .input>* { vertical-align: middle; white-space: nowrap; } .control-panel .input label { text-transform: uppercase; width: 50%; margin-right: 10%; color: #486865; margin-bottom: 4px; } .control-panel .input input, .control-panel .input a { font-size: 0.9em; display: inline-block; padding: 0 4px; width: 40%; height: 20px; line-height: 1.833; } .control-panel .input input[type="checkbox"], .control-panel .input input[type="radio"], .control-panel .input input[type="color"] { width: 20%; } .control-panel .input input { border: solid 1px #ccc; } .control-panel .input input:disabled { background: #fff; } .control-panel .input input[type="checkbox"] { height: auto; } .control-panel .input .tooltip { left: 50%; top: 24px; opacity: 0; pointer-events: none; transition: opacity 200ms; } .control-panel .input:hover .tooltip { opacity: 1; }