{"id":19220061,"url":"https://github.com/nativescript-community/ui-mapbox","last_synced_at":"2025-04-05T17:02:55.980Z","repository":{"id":43024841,"uuid":"312237318","full_name":"nativescript-community/ui-mapbox","owner":"nativescript-community","description":"Interactive, thoroughly customizable maps powered by vector tiles and OpenGL.","archived":false,"fork":false,"pushed_at":"2024-12-02T16:14:12.000Z","size":57871,"stargazers_count":35,"open_issues_count":50,"forks_count":25,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-03-29T16:07:28.968Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nativescript-community.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["farfromrefug"]}},"created_at":"2020-11-12T10:07:46.000Z","updated_at":"2025-03-19T07:09:48.000Z","dependencies_parsed_at":"2023-12-07T17:32:57.506Z","dependency_job_id":"2fff6970-bcc5-4f8f-b26d-8d7c438016d1","html_url":"https://github.com/nativescript-community/ui-mapbox","commit_stats":{"total_commits":608,"total_committers":51,"mean_commits":11.92156862745098,"dds":0.6792763157894737,"last_synced_commit":"e5fa6d76aae45d35f8f4bacf7617423e77130f12"},"previous_names":[],"tags_count":86,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nativescript-community%2Fui-mapbox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nativescript-community%2Fui-mapbox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nativescript-community%2Fui-mapbox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nativescript-community%2Fui-mapbox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nativescript-community","download_url":"https://codeload.github.com/nativescript-community/ui-mapbox/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247369950,"owners_count":20927928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T14:33:51.901Z","updated_at":"2025-04-05T17:02:55.963Z","avatar_url":"https://github.com/nativescript-community.png","language":"TypeScript","funding_links":["https://github.com/sponsors/farfromrefug"],"categories":["Plugins"],"sub_categories":["Geo Plugins"],"readme":"\u003c!-- ⚠️ This README has been generated from the file(s) \"blueprint.md\" ⚠️--\u003e\u003c!-- ⚠️ This README has been generated from the file(s) \"blueprint.md\" ⚠️--\u003e\n\u003c!--  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      DO NOT EDIT THIS READEME DIRECTLY! Edit \"bluesprint.md\" instead.\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n      !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --\u003e\n\u003ch1 align=\"center\"\u003e@nativescript-community/ui-mapbox\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n\t\t\u003ca href=\"https://npmcharts.com/compare/@nativescript-community/ui-mapbox?minimal=true\"\u003e\u003cimg alt=\"Downloads per month\" src=\"https://img.shields.io/npm/dm/@nativescript-community/ui-mapbox.svg\" height=\"20\"/\u003e\u003c/a\u003e\r\n\u003ca href=\"https://www.npmjs.com/package/@nativescript-community/ui-mapbox\"\u003e\u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/@nativescript-community/ui-mapbox.svg\" height=\"20\"/\u003e\u003c/a\u003e\n\t\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eInteractive, thoroughly customizable maps powered by vector tiles and OpenGL.\u003c/b\u003e\u003c/br\u003e\n  \u003csub\u003e\u003csub\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n\n\r\n[](#table-of-contents)\r\n\r\n\r\n[](#table-of-contents)\r\n\r\n## Table of Contents\n\n* [Prerequisites](#prerequisites)\r\n\t* [Android](#android)\r\n* [Installation](#installation)\r\n* [Configuration](#configuration)\r\n* [Issues](#issues)\r\n* [Usage](#usage)\r\n\t* [XML](#xml)\r\n\t* [Angular](#angular)\r\n* [API](#api)\r\n* [Markers](#markers)\r\n* [Viewport](#viewport)\r\n* [Declaring Programmatically](#declaring-programmatically)\r\n* [Methods](#methods)\r\n\t* [show](#show)\r\n\t* [hide](#hide)\r\n\t* [unhide](#unhide)\r\n\t* [destroy 💥](#destroy-)\r\n\t* [setMapStyle](#setmapstyle)\r\n\t* [addMarkers](#addmarkers)\r\n\t* [Updating markers](#updating-markers)\r\n\t* [removeMarkers](#removemarkers)\r\n\t* [setViewport](#setviewport)\r\n\t* [getViewport](#getviewport)\r\n\t* [setCenter](#setcenter)\r\n\t* [getCenter](#getcenter)\r\n\t* [setZoomLevel](#setzoomlevel)\r\n\t* [getZoomLevel](#getzoomlevel)\r\n\t* [animateCamera](#animatecamera)\r\n\t* [setTilt (Android only)](#settilt-android-only)\r\n\t* [getTilt (Android only)](#gettilt-android-only)\r\n\t* [getUserLocation](#getuserlocation)\r\n\t* [trackUser](#trackuser)\r\n\t* [addSource](#addsource)\r\n\t* [removeSource](#removesource)\r\n\t* [addLayer](#addlayer)\r\n\t* [removeLayer](#removelayer)\r\n\t* [queryRenderedFeatures](#queryrenderedfeatures)\r\n\t* [querySourceFeatures](#querysourcefeatures)\r\n\t* [addLinePoint](#addlinepoint)\r\n\t* [addPolygon (**deprecated**, use addLayer() instead)](#addpolygon-deprecated-use-addlayer-instead)\r\n\t* [removePolygons](#removepolygons)\r\n\t* [addPolyline](#addpolyline)\r\n\t* [removePolylines](#removepolylines)\r\n\t* [setOnMapClickListener](#setonmapclicklistener)\r\n\t* [setOnMapLongClickListener](#setonmaplongclicklistener)\r\n\t* [setOnScrollListener](#setonscrolllistener)\r\n* [Offline maps](#offline-maps)\r\n\t* [downloadOfflineRegion](#downloadofflineregion)\r\n\t\t* [Advanced example: download the current viewport](#advanced-example-download-the-current-viewport)\r\n\t* [listOfflineRegions](#listofflineregions)\r\n\t* [deleteOfflineRegion](#deleteofflineregion)\r\n* [Permissions](#permissions)\r\n\t* [hasFineLocationPermission / requestFineLocationPermission](#hasfinelocationpermission--requestfinelocationpermission)\r\n* [Using marker images from the internet](#using-marker-images-from-the-internet)\r\n* [Demos and Development](#demos-and-development)\r\n\t* [Repo Setup](#repo-setup)\r\n\t* [Build](#build)\r\n\t* [Demos](#demos)\r\n* [Contributing](#contributing)\r\n\t* [Update repo ](#update-repo-)\r\n\t* [Update readme ](#update-readme-)\r\n\t* [Update doc ](#update-doc-)\r\n\t* [Publish](#publish)\r\n\t* [modifying submodules](#modifying-submodules)\r\n* [Questions](#questions)\n\n\r\n[](#prerequisites)\r\n\r\n\r\n[](#prerequisites)\r\n\r\n## Prerequisites\n\nYou either need your own tile server such as the one provided by [openmaptiles.org](https://openmaptiles.org) or a Mapbox API access token (they have a 🆓 Starter plan!), so [sign up with Mapbox](https://www.mapbox.com/signup/).\nOnce you've registered go to your Account \u003e Apps \u003e New token. The 'Default Secret Token' is what you'll need.\n\n### Android\n\nMapbox now requires (version \u003e 8.6.6) an api key to download the sdk\n\nIf you want to use newer version than the default 8.6.6 you need to add this to your `app.gradle`\n```gradle\nallprojects {\n  repositories {\n       maven {\n        url 'https://api.mapbox.com/downloads/v2/releases/maven'\n        authentication {\n            basic(BasicAuthentication)\n        }\n        credentials {\n            // Do not change the username below.\n            // This should always be `mapbox` (not your username). \n            username = 'mapbox'\n            // Use the secret token you stored in gradle.properties as the password\n            password = project.properties['MAPBOX_DOWNLOADS_TOKEN'] ?: \"\"\n        }\n    }\n  }\n}\n```\n\n\r\n[](#installation)\r\n\r\n\r\n[](#installation)\r\n\r\n## Installation\nRun the following command from the root of your project:\n\n`ns plugin add @nativescript-community/ui-mapbox`\n\n\r\n[](#configuration)\r\n\r\n\r\n[](#configuration)\r\n\r\n## Configuration\n\nAdd any other additional configuration instructions here.\n\n\r\n[](#issues)\r\n\r\n\r\n[](#issues)\r\n\r\n## Issues\n\nIf you get an error during iOS build related to Podspec versions, probably the easiest fix is:\n`ns platform remove ios` and `ns platform add ios`.\n\nOn Android the plugin adds this to the `\u003capplication\u003e` node of `app/App_Resources/Android/AndroidManifest.xml` (the plugin already attempts to do so):\n\n```xml\n  \u003cservice android:name=\"com.mapbox.services.android.telemetry.service.TelemetryService\" /\u003e\n```\n\nIf you get an error related to `TelemetryService` then please check it's there.\n\n\r\n[](#usage)\r\n\r\n\r\n[](#usage)\r\n\r\n## Usage\n\n### XML\nYou can instantiate a map from JS or TS. As the map is yet another view component it will play nice with any NativeScript layout you throw it in. You can also easily add multiple maps to the same page or to different pages in any layout you like.\n\nA simple layout could look like this:\n\n\u003cimg src=\"https://raw.githubusercontent.com/nativescript-community/ui-mapbox/master/images/ios-xml-declared.png\" width=\"373px\" height=\"361px\" /\u003e\n\nCould be rendered by a definition like this:\n\n```xml\n\u003cPage xmlns=\"http://schemas.nativescript.org/tns.xsd\" xmlns:map=\"@nativescript-community/ui-mapbox\" navigatingTo=\"navigatingTo\"\u003e\n  \u003cStackLayout\u003e\n    \u003cLabel text=\"Nice map, huh!\" class=\"title\"/\u003e\n    \u003cContentView height=\"240\" width=\"240\"\u003e\n      \u003cmap:MapboxView\n          accessToken=\"your_token\"\n          mapStyle=\"traffic_night\"\n          latitude=\"52.3702160\"\n          longitude=\"4.8951680\"\n          zoomLevel=\"3\"\n          showUserLocation=\"true\"\n          mapReady=\"onMapReady\"\u003e\n      \u003c/map:MapboxView\u003e\n    \u003c/ContentView\u003e\n  \u003c/StackLayout\u003e\n\u003c/Page\u003e\n```\n\n### Angular\nComponent:\n\n```typescript\nimport { registerElement } from '@nativescript/angular';\nregisterElement(\"Mapbox\", () =\u003e require(\"@nativescript-community/ui-mapbox\").MapboxView);\n```\n\nView:\n\n```html\n  \u003cContentView height=\"100%\" width=\"100%\"\u003e\n    \u003cMapbox\n        accessToken=\"your_token\"\n        mapStyle=\"traffic_day\"\n        latitude=\"50.467735\"\n        longitude=\"13.427718\"\n        hideCompass=\"true\"\n        zoomLevel=\"18\"\n        showUserLocation=\"false\"\n        disableZoom=\"false\"\n        disableRotation=\"false\"\n        disableScroll=\"false\"\n        disableTilt=\"false\"\n        (mapReady)=\"onMapReady($event)\"\u003e\n    \u003c/Mapbox\u003e\n  \u003c/ContentView\u003e\n```\n\n\r\n[](#api)\r\n\r\n\r\n[](#api)\r\n\r\n## API\nAll currently supported options for your XML based map are (__don't__ use other properties - if you need styling wrap the map in a `ContentView` and apply things like `width` to that container!):\n\n|option|default|description\n|---|---|---\n|`accesstoken`|-|see 'Prerequisites' above\n|`delay`|0|A delay in milliseconds - you can set this to have better control over when Mapbox is invoked so it won't clash with other computations your app may need to perform.\n|`mapStyle`|streets|streets, light, dark, satellite_streets, satellite, traffic_day, traffic_night, an URL starting with mapbox:// or pointing to a custom JSON definition (http://, https://, or local relative to nativescript app path ~/)\n|`latitude `|-|Set the center of the map by passing this in\n|`longitude`|-|.. and this as well\n|`zoomLevel`|0|0-20\n|`showUserLocation `|false|Requires location permissions on Android which you can remove from `AndroidManifest.xml` if you don't need them\n|`hideCompass `|false|Don't show the compass in the top right corner during rotation of the map\n|`hideLogo`|false|Mapbox requires `false` if you're on a free plan\n|`hideAttribution `|true|Mapbox requires `false` if you're on a free plan\n|`disableZoom`|false|Don't allow the user to zoom in or out (pinch and double-tap)\n|`disableRotation`|false|Don't allow the user to rotate the map (two finger gesture)\n|`disableScroll`|false|Don't allow the user to move the center of the map (one finger drag)\n|`disableTilt`|false|Don't allow the user to tilt the map (two finger drag up or down)\n|`mapReady`|-|The name of a callback function you can declare to interact with the map after it has been drawn\n|`moveBeginEvent`|-|The name of a function to be called when the map has begun to move.\n|`moveEndEvent`|-|The name of a function to be called when the map has completed moving.\n|`locationPermissionGranted`|-|The name of a callback function you can declare to get notified when the user granted location permissions\n|`locationPermissionDenied`|-|The name of a callback function you can declare to get notified when the user denied location permissions (will never fire on iOS because there's nothing to deny)\n\n\r\n[](#markers)\r\n\r\n\r\n[](#markers)\r\n\r\n## Markers\nThis is where that last option in the table above comes in - `mapReady`.\nIt allows you to interact with the map after it has been drawn to the page.\n\nOpen `main-page.[js|ts]` and add this (see [`addMarkers`](#addmarkers) further below for the full marker API):\n\n```js\nvar mapbox = require(\"@nativescript-community/ui-mapbox\");\n\nfunction onMapReady(args) {\n  // you can tap into the native MapView objects (MGLMapView for iOS and com.mapbox.mapboxsdk.maps.MapView for Android)\n  var nativeMapView = args.ios ? args.ios : args.android;\n  console.log(\"Mapbox onMapReady for \" + (args.ios ? \"iOS\" : \"Android\") + \", native object received: \" + nativeMapView);\n\n  // .. or use the convenience methods exposed on args.map, for instance:\n  args.map.addMarkers([\n    {\n      lat: 52.3602160,\n      lng: 4.8891680,\n      title: 'One-line title here',\n      subtitle: 'Really really nice location',\n      selected: true, // makes the callout show immediately when the marker is added (note: only 1 marker can be selected at a time)\n      onCalloutTap: function(){console.log(\"'Nice location' marker callout tapped\");}\n    }]\n  );\n}\n\nexports.onMapReady = onMapReady;\n```\n\n\r\n[](#viewport)\r\n\r\n\r\n[](#viewport)\r\n\r\n## Viewport\n\n```js\nvar mapbox = require(\"@nativescript-community/ui-mapbox\");\n\nfunction onMapReady(args) {\n  args.map.setViewport(\n      {\n        bounds: {\n          north: 52.4820,\n          east: 5.1087,\n          south: 52.2581,\n          west: 4.6816\n        },\n        animated: true\n      }\n  );\n}\n\nexports.onMapReady = onMapReady;\n```\n\nThe methods you can invoke like this from an XML-declared map are:\n`addMarkers`, `setViewport`, `removeMarkers`, `getCenter`, `setCenter`, `getZoomLevel`, `setZoomLevel`, `getViewport`, `getTilt`, `setTilt`, `setMapStyle`, `animateCamera`, `addPolygon`, `removePolygons`, `addPolyline`, `removePolylines`, `getUserLocation`, `trackUser`, `setOnMapClickListener`, `setOnMapLongClickListener` and `destroy`.\n\nCheck out the usage details on the functions below.\n\n\r\n[](#declaring-programmatically)\r\n\r\n\r\n[](#declaring-programmatically)\r\n\r\n## Declaring Programmatically\n\nAdd a container to your view XML where you want to programmatically add the map. Give it an id. \n\n```\n\u003cContentView id=\"mapContainer\" /\u003e\n```\n\n\r\n[](#methods)\r\n\r\n\r\n[](#methods)\r\n\r\n## Methods\n\n### show\n```ts\n\n    const contentView : ContentView = \u003cContentView\u003epage.getViewById( 'mapContainer' );\n\n    const settings = {\n\n      // NOTE: passing in the container here.\n\n      container: contentView,\n      accessToken: ACCESS_TOKEN,\n      style: MapStyle.LIGHT,\n      margins: {\n        left: 18,\n        right: 18,\n        top: isIOS ? 390 : 454,\n        bottom: isIOS ? 50 : 8\n      },\n      center: {\n        lat: 52.3702160,\n        lng: 4.8951680\n      },\n      zoomLevel: 9, // 0 (most of the world) to 20, default 0\n      showUserLocation: true, // default false\n      hideAttribution: true, // default false\n      hideLogo: true, // default false\n      hideCompass: false, // default false\n      disableRotation: false, // default false\n      disableScroll: false, // default false\n      disableZoom: false, // default false\n      disableTilt: false, // default false\n      markers: [\n        {\n          id: 1,\n          lat: 52.3732160,\n          lng: 4.8941680,\n          title: 'Nice location',\n          subtitle: 'Really really nice location',\n          iconPath: 'res/markers/green_pin_marker.png',\n          onTap: () =\u003e console.log(\"'Nice location' marker tapped\"),\n          onCalloutTap: () =\u003e console.log(\"'Nice location' marker callout tapped\")\n        }\n      ]\n    };\n\n    console.log( \"main-view-model:: doShow(): creating new MapboxView.\" );\n\n    const mapView = new MapboxView();\n\n    // Bind some event handlers onto our newly created map view. \n\n    mapView.on( 'mapReady', ( args : any ) =\u003e {\n\n      console.log( \"main-view-model: onMapReady fired.\" );\n\n      // this is an instance of class MapboxView\n\n      this.mapboxView = args.map;\n\n      // get a reference to the Mapbox API shim object so we can directly call its methods.\n\n      this.mapbox = this.mapboxView.getMapboxApi();\n\n      this.mapbox.setOnMapClickListener( point =\u003e {\n        console.log(`\u003e\u003e Map clicked: ${JSON.stringify(point)}`);\n        return true;\n      });\n\n      this.mapbox.setOnMapLongClickListener( point =\u003e {\n        console.log(`\u003e\u003e Map longpressed: ${JSON.stringify(point)}`);\n        return true;\n      });\n\n      this.mapbox.setOnScrollListener((point: LatLng) =\u003e {\n        // console.log(`\u003e\u003e Map scrolled`);\n      });\n\n      this.mapbox.setOnFlingListener(() =\u003e {\n        console.log(`\u003e\u003e Map flinged\"`);\n      }).catch( err =\u003e console.log(err) );\n\n    });\n\n    mapView.setConfig( settings );\n    contentView.content = mapView;\n  \n```\n\n### hide\nAll further examples assume `mapbox` has been required.\nAlso, all functions support promises, but we're leaving out the `.then()` stuff for brevity where it doesn't add value.\n```js\n  mapbox.hide();\n```\n\n### unhide\nIf you previously called `hide()` you can quickly unhide the map,\ninstead of redrawing it (which is a lot slower and you loose the viewport position, etc).\n\n```js\n  mapbox.unhide();\n```\n\n### destroy 💥\nTo clean up the map entirely you can destroy instead of hide it:\n\n```js\n  mapbox.destroy();\n```\n\n### setMapStyle\nYou can update the map style after you've loaded it.\n\n\u003e With Mapbox Android SDK 6.1.x (used in plugin version 4.1.0) I've seen Android crash a few seconds after this has been used, so test this well and perhaps don't use it when in doubt.\n\n```js\n  mapbox.setMapStyle(mapbox.MapStyle.DARK);\n```\n\n### addMarkers\n\n```typescript\n  import { MapboxMarker } from \"@nativescript-community/ui-mapbox\";\n\n  const firstMarker = \u003cMapboxMarker\u003e{ //cast as a MapboxMarker to pick up helper functions such as update()\n    id: 2, // can be user in 'removeMarkers()'\n    lat: 52.3602160, // mandatory\n    lng: 4.8891680, // mandatory\n    title: 'One-line title here', // no popup unless set\n    subtitle: 'Infamous subtitle!',\n    // icon: 'res://cool_marker', // preferred way, otherwise use:\n    icon: 'http(s)://website/coolimage.png', // from the internet (see the note at the bottom of this readme), or:\n    iconPath: '~/assets/markers/home_marker.png',\n    selected: true, // makes the callout show immediately when the marker is added (note: only 1 marker can be selected at a time)\n    onTap: marker =\u003e console.log(\"Marker tapped with title: '\" + marker.title + \"'\"),\n    onCalloutTap: marker =\u003e alert(\"Marker callout tapped with title: '\" + marker.title + \"'\")\n  };\n\n  mapbox.addMarkers([\n    firstMarker,\n    {\n      // more markers..\n    }\n  ])\n```\n\n### Updating markers\nPlugin version 4.2.0 added the option to update makers. Just call `update` on the `MapboxMarker` reference you created above.\nYou can update the following properties (all but the icon really):\n\n```typescript\n  firstMarker.update({\n    lat: 52.3622160,\n    lng: 4.8911680,\n    title: 'One-line title here (UPDATE)',\n    subtitle: 'Updated subtitle',\n    selected: true, // this will trigger the callout upon update\n    onTap: (marker: MapboxMarker) =\u003e console.log(`UPDATED Marker tapped with title: ${marker.title}`),\n    onCalloutTap: (marker: MapboxMarker) =\u003e alert(`UPDATED Marker callout tapped with title: ${marker.title}`)\n  })\n```\n\n### removeMarkers\nYou can either remove all markers by not passing in an argument,\nor remove specific marker id's (which you specified previously).\n\n```js\n  // remove all markers\n  mapbox.removeMarkers();\n\n  // remove specific markers by id\n  mapbox.removeMarkers([1, 2]);\n```\n\n### setViewport\nIf you want to for instance make the viewport contain all markers you\ncan set the bounds to the lat/lng of the outermost markers using this function.\n\n```js\n  mapbox.setViewport(\n      {\n        bounds: {\n          north: 52.4820,\n          east: 5.1087,\n          south: 52.2581,\n          west: 4.6816\n        },\n        animated: true // default true\n      }\n  )\n```\n\n### getViewport\n```js\n  mapbox.getViewport().then(\n      function(result) {\n        console.log(\"Mapbox getViewport done, result: \" + JSON.stringify(result));\n      }\n  )\n```\n\n\n### setCenter\n```js\n  mapbox.setCenter(\n      {\n        lat: 52.3602160, // mandatory\n        lng: 4.8891680, // mandatory\n        animated: false // default true\n      }\n  )\n```\n\n### getCenter\nHere the promise callback makes sense, so adding it to the example:\n```js\n  mapbox.getCenter().then(\n      function(result) {\n        console.log(\"Mapbox getCenter done, result: \" + JSON.stringify(result));\n      },\n      function(error) {\n        console.log(\"mapbox getCenter error: \" + error);\n      }\n  )\n```\n\n### setZoomLevel\n```js\n  mapbox.setZoomLevel(\n      {\n        level: 6.5, // mandatory, 0-20\n        animated: true // default true\n      }\n  )\n```\n\n### getZoomLevel\n```js\n  mapbox.getZoomLevel().then(\n      function(result) {\n        console.log(\"Mapbox getZoomLevel done, result: \" + JSON.stringify(result));\n      },\n      function(error) {\n        console.log(\"mapbox getZoomLevel error: \" + error);\n      }\n  )\n```\n\n### animateCamera\n\n```js\n  // this is a boring triangle drawn near Amsterdam Central Station\n  mapbox.animateCamera({\n    // this is where we animate to\n    target: {\n        lat: 52.3732160,\n        lng: 4.8941680\n    },\n    zoomLevel: 17, // Android\n    altitude: 2000, // iOS (meters from the ground)\n    bearing: 270, // Where the camera is pointing, 0-360 (degrees)\n    tilt: 50,\n    duration: 5000 // default 10000 (milliseconds)\n  })\n```\n\n### setTilt (Android only)\n```js\n  mapbox.setTilt(\n      {\n        tilt: 40, // default 30 (degrees angle)\n        duration: 4000 // default 5000 (milliseconds)\n      }\n  )\n```\n\n### getTilt (Android only)\n```js\n  mapbox.getTilt().then(\n      function(tilt) {\n        console.log(\"Current map tilt: \" +  tilt);\n      }\n  )\n```\n\n### getUserLocation\nIf the user's location is shown on the map you can get their coordinates and speed:\n\n```js\n  mapbox.getUserLocation().then(\n      function(userLocation) {\n        console.log(\"Current user location: \" +  userLocation.location.lat + \", \" + userLocation.location.lng);\n        console.log(\"Current user speed: \" +  userLocation.speed);\n      }\n  )\n```\n\n### trackUser\nIn case you're showing the user's location, you can have the map track the position.\nThe map will continuously move along with the last known location.\n\n```js\n  mapbox.trackUser({\n    mode: \"FOLLOW_WITH_HEADING\", // \"NONE\" | \"FOLLOW\" | \"FOLLOW_WITH_HEADING\" | \"FOLLOW_WITH_COURSE\"\n    animated: true\n  });\n```\n\n### addSource\n\nhttps://docs.mapbox.com/mapbox-gl-js/api/#map#addsource \n\nSupported source types:\n - Vector\n - GeoJson \n - Raster\n\nAdds a vector to GeoJSON source to the map.\n\n```js\n  mapbox.addSource( id, {\n    type: 'vector',\n    url: 'url to source'\n  } );\n```\n\n-or-\n\n```js\n  mapbox.addSource( id, {\n    'type': 'geojson',\n    'data': {\n      \"type\": \"Feature\",\n        \"geometry\": {\n        \"type\": \"LineString\",\n          \"coordinates\": [ [ lng, lat ], [ lng, lat ], ..... ]\n        }\n      }\n    }\n  );\n```\n### removeSource\n\nRemove a source by id\n\n```js\n  mapbox.removeSource( id );\n```\n\n### addLayer\nhttps://docs.mapbox.com/mapbox-gl-js/style-spec/#layers\n \nSupported layer types:\n - Line\n - Circle \n - Fill\n - Symbol\n - Raster\n\nTo add a line:\n\n```js\n  mapbox.addLayer({\n    'id': someid,\n    'type': 'line',\n    'source': {\n      'type': 'geojson',\n      'data': {\n        \"type\": \"Feature\",\n          \"geometry\": {\n          \"type\": \"LineString\",\n            \"coordinates\": [ [ lng, lat ], [ lng, lat ], ..... ]\n          }\n        }\n      }\n    },\n    'layout': {\n      'line-cap': 'round',\n      'line-join': 'round'\n    },    \n    'paint': {\n      'line-color': '#ed6498',\n      'line-width': 5,\n      'line-opacity': .8,\n      'line-dash-array': [ 1, 1, 1, ..]\n    }\n  });\n```\n\nTo add a circle:\n\n```js\n  mapbox.addLayer({\n    \"id\": someid,\n    \"type\": 'circle',\n    \"source\": {\n      \"type\": 'geojson',\n      \"data\": {\n        \"type\": \"Feature\",\n        \"geometry\": {\n          \"type\": \"Point\",\n          \"coordinates\": [ lng, lat ]\n        }\n      }\n    }, \n    \"paint\": {\n      \"circle-radius\": {\n        \"stops\": [\n          [0, 0],\n          [20, 8000 ]\n        ],\n        \"base\": 2\n      },\n      'circle-opacity': 0.05,\n      'circle-color': '#ed6498',\n      'circle-stroke-width': 2,\n      'circle-stroke-color': '#ed6498'\n    } \n  });\n```\n\nSource may be a geojson or vector source description or may be \nthe id of a source added using addSource()\n\n### removeLayer\nRemove a layer added with addLayer() by id.\n\n```js\n  mapbox.removeLayer( id );\n```\n\n### queryRenderedFeatures\nhttps://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures\nReturns an array of GeoJSON Feature objects representing visible features that satisfy the query parameters.\n\n```js\nmapbox\n  .queryRenderedFeatures({\n    point: {\n      lat: 52.3701494345567,\n      lng: 4.823684692382513,\n  \t},\n    layers: ['circle-with-source-object'],\n    filter: ['==', ['get', 'querySample'], '2'],\n  })\n  .then((result) =\u003e console.log('query rendered features', result))\n```\n\n### querySourceFeatures\nhttps://docs.mapbox.com/mapbox-gl-js/api/map/#map#querysourcefeatures\nReturns an array of GeoJSON Feature objects representing features within the specified vector tile or GeoJSON source that satisfy the query parameters.\n\n```js\nmapbox\n  .querySourceFeatures('source_id', { filter: ['==', ['get', 'querySample'], '2'] })\n  .then((result) =\u003e console.log('query source features', result));\n```\n\n### addLinePoint\nDynamically add a point to a line.\n\n```js\n  mapbox.addLinePoint( \u003cid of line layer\u003e, lnglat )\n```\n\nwhere lnglat is an array of two points, a longitude and a latitude.\n\n### addPolygon (**deprecated**, use addLayer() instead)\n\nDraw a shape. Just connect the dots like we did as a toddler.\n\nThe first person to tweet a snowman drawn with this function gets a T-shirt (from @eddyverbruggen ;-)).\n\n```typescript\n  // after adding this, scroll to Amsterdam to see a semi-transparent red square\n  mapbox.addPolygon(\n      {\n        id: 1, // optional, can be used in 'removePolygons'\n        fillColor: new Color(\"red\"),\n        fillOpacity: 0.7,\n\n        // stroke-related properties are only effective on iOS\n        strokeColor: new Color(\"green\"),\n        strokeWidth: 8,\n        strokeOpacity: 0.5,\n\n        points: [\n          {\n            lat: 52.3923633970718,\n            lng: 4.902648925781249\n          },\n          {\n            lat: 52.35421556258807,\n            lng: 4.9308013916015625\n          },\n          {\n            lat: 52.353796172573944,\n            lng: 4.8799896240234375\n          },\n          {\n            lat: 52.3864966440161,\n            lng: 4.8621368408203125\n          },\n          {\n            lat: 52.3923633970718,\n            lng: 4.902648925781249\n          }\n        ]\n      })\n      .then(result =\u003e console.log(\"Mapbox addPolygon done\"))\n      .catch((error: string) =\u003e console.log(\"mapbox addPolygon error: \" + error));\n```\n\n### removePolygons\nYou can either remove all polygons by not passing in an argument,\nor remove specific polygon id's (which you specified previously).\n\n```js\n  // remove all polygons\n  mapbox.removePolygons();\n\n  // remove specific polygons by id\n  mapbox.removePolygons([1, 2]);\n```\n\n### addPolyline\nDeprecated. Use addLayer() instead.\n\nDraw a polyline. Connect the points given as parameters.\n\n```js\n  // Draw a two segment line near Amsterdam Central Station\n  mapbox.addPolyline({\n      id: 1, // optional, can be used in 'removePolylines'\n      color: '#336699', // Set the color of the line (default black)\n      width: 7, // Set the width of the line (default 5)\n      opacity: 0.6, //Transparency / alpha, ranging 0-1. Default fully opaque (1).\n      points: [\n          {\n              'lat': 52.3833160, // mandatory\n              'lng': 4.8991780 // mandatory\n          },\n          {\n              'lat': 52.3834160,\n              'lng': 4.8991880\n          },\n          {\n              'lat': 52.3835160,\n              'lng': 4.8991980\n          }\n      ]\n  });\n```\n\n### removePolylines\nDeprecated. Use removeLayer() instead.\n\nYou can either remove all polylines by not passing in an argument,\nor remove specific polyline id's (which you specified previously).\n\n```js\n  // remove all polylines\n  mapbox.removePolylines();\n\n  // remove specific polylines by id\n  mapbox.removePolylines([1, 2]);\n```\n\n### setOnMapClickListener\nAdd a listener to retrieve lat and lng of where the user taps the map (not a marker).\n\n```typescript\n  mapbox.setOnMapClickListener((point: LatLng) =\u003e {\n    console.log(\"Map clicked at latitude: \" + point.lat + \", longitude: \" + point.lng);\n  });\n```\n\n### setOnMapLongClickListener\nAdd a listener to retrieve lat and lng of where the user longpresses the map (not a marker).\n\n```typescript\n  mapbox.setOnMapLongClickListener((point: LatLng) =\u003e {\n    console.log(\"Map longpressed at latitude: \" + point.lat + \", longitude: \" + point.lng);\n  });\n```\n\n### setOnScrollListener\nAdd a listener to retrieve lat and lng of where the user scrolls to on the map.\n\n```typescript\n  mapbox.setOnScrollListener((point?: LatLng) =\u003e {\n    console.log(\"Map scrolled to latitude: \" + point.lat + \", longitude: \" + point.lng);\n  });\n```\n\n\r\n[](#offline-maps)\r\n\r\n\r\n[](#offline-maps)\r\n\r\n## Offline maps\nFor situations where you want the user to pre-load certain regions you can use these methods to create and remove offline regions.\n\n__Important read:__ [the offline maps documentation by Mapbox](https://www.mapbox.com/help/mobile-offline/).\n\n### downloadOfflineRegion\nThis example downloads the region 'Amsterdam' on zoom levels 9, 10 and 11 for map style 'outdoors'.\n\n```js\n  mapbox.downloadOfflineRegion(\n    {\n      accessToken: accessToken, // required for Android in case no map has been shown yet\n      name: \"Amsterdam\", // this name can be used to delete the region later\n      style: mapbox.MapStyle.OUTDOORS,\n      minZoom: 9,\n      maxZoom: 11,\n      bounds: {\n        north: 52.4820,\n        east: 5.1087,\n        south: 52.2581,\n        west: 4.6816\n      },\n      // this function is called many times during a download, so\n      // use it to show an awesome progress bar!\n      onProgress: function (progress) {\n        console.log(\"Download progress: \" + JSON.stringify(progress));\n      }\n    }\n  ).then(\n    function() {\n      console.log(\"Offline region downloaded\");\n    },\n    function(error) {\n      console.log(\"Download error: \" + error);\n    }\n  );\n```\n\n#### Advanced example: download the current viewport\nGrab the viewport with the `mapbox.getViewport()` function and download it at various zoom levels:\n\n```js\n  // I spare you the error handling on this one..\n  mapbox.getViewport().then(function(viewport) {\n    mapbox.downloadOfflineRegion(\n      {\n        name: \"LastViewport\", // anything you like really\n        style: mapbox.MapStyle.LIGHT,\n        minZoom: viewport.zoomLevel,\n        maxZoom: viewport.zoomLevel + 2, // higher zoom level is lower to the ground\n        bounds: viewport.bounds,\n        onProgress: function (progress) {\n          console.log(\"Download %: \" + progress.percentage);\n        }\n      }\n    );\n  });\n```\n\n### listOfflineRegions\nTo help you manage offline regions there's a `listOfflineRegions` function you can use. You can then fi. call `deleteOfflineRegion` (see below) and pass in the `name` to remove any cached region(s) you like.\n\n```js\n  mapbox.listOfflineRegions({\n    // required for Android in case no map has been shown yet\n    accessToken: accessToken\n  }).then(\n    function(regions) {\n      console.log(JSON.stringify(JSON.stringify(regions));\n    },\n    function(error) {\n      console.log(\"Error while listing offline regions: \" + error);\n    }\n  );\n\n```\n\n### deleteOfflineRegion\nYou can remove regions you've previously downloaded. Any region(s) matching the `name` param will be removed locally.\n\n```js\n  mapbox.deleteOfflineRegion({\n    name: \"Amsterdam\"\n  }).then(\n    function() {\n      console.log(\"Offline region deleted\");\n    },\n    function(error) {\n      console.log(\"Error while deleting an offline region: \" + error);\n    }\n  );\n```\n\n\n\r\n[](#permissions)\r\n\r\n\r\n[](#permissions)\r\n\r\n## Permissions\n\n### hasFineLocationPermission / requestFineLocationPermission\nOn Android 6 you need to request permission to be able to show the user's position on the map at runtime when targeting API level 23+.\nEven if the `uses-permission` tag for `ACCESS_FINE_LOCATION` is present in `AndroidManifest.xml`.\n\n**You don't need to do this with plugin version 2.4.0+ as permission is request when required while rendering the map. You're welcome :)**\n\nNote that `hasFineLocationPermission` will return true when:\n* You're running this on iOS, or\n* You're targeting an API level lower than 23, or\n* You're using Android \u003c 6, or\n* You've already granted permission.\n\n```js\n  mapbox.hasFineLocationPermission().then(\n      function(granted) {\n        // if this is 'false' you probably want to call 'requestFineLocationPermission' now\n        console.log(\"Has Location Permission? \" + granted);\n      }\n  );\n\n  // if no permission was granted previously this will open a user consent screen\n  mapbox.requestFineLocationPermission().then(\n      function() {\n        console.log(\"Location permission requested\");\n      }\n  );\n```\n\nNote that the `show` function will also check for permission if you passed in `showUserLocation : true`.\nIf you didn't request permission before showing the map, and permission was needed, the plugin will ask the user permission while rendering the map.\n\n\r\n[](#using-marker-images-from-the-internet)\r\n\r\n\r\n[](#using-marker-images-from-the-internet)\r\n\r\n## Using marker images from the internet\nIf you specify `icon: 'http(s)://some-remote-image'`, then on iOS you'll need to whitelist\nthe domain. Google for iOS ATS for detailed options, but for a quick test you can add this to\n`app/App_Resources/iOS/Info.plist`:\n\n```xml\n\t\u003ckey\u003eNSAppTransportSecurity\u003c/key\u003e\n\t\u003cdict\u003e\n        \u003ckey\u003eNSAllowsArbitraryLoads\u003c/key\u003e\n        \u003ctrue/\u003e\n\t\u003c/dict\u003e\n```\n\n\r\n[](#demos-and-development)\r\n\r\n\r\n[](#demos-and-development)\r\n\r\n## Demos and Development\n\n\n### Repo Setup\n\nThe repo uses submodules. If you did not clone with ` --recursive` then you need to call\n```\ngit submodule update --init\n```\n\nThe package manager used to install and link dependencies must be `pnpm` or `yarn`. `npm` wont work.\n\nTo develop and test:\nif you use `yarn` then run `yarn`\nif you use `pnpm` then run `pnpm i`\n\n**Interactive Menu:**\n\nTo start the interactive menu, run `npm start` (or `yarn start` or `pnpm start`). This will list all of the commonly used scripts.\n\n### Build\n\n```bash\nnpm run build.all\n```\nWARNING: it seems `yarn build.all` wont always work (not finding binaries in `node_modules/.bin`) which is why the doc explicitly uses `npm run`\n\n### Demos\n\n```bash\nnpm run demo.[ng|react|svelte|vue].[ios|android]\n\nnpm run demo.svelte.ios # Example\n```\n\nDemo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in `demo-[ng|react|svelte|vue]`\nInstead you work in `demo-snippets/[ng|react|svelte|vue]`\nYou can start from the `install.ts` of each flavor to see how to register new demos \n\n\r\n[](#contributing)\r\n\r\n\r\n[](#contributing)\r\n\r\n## Contributing\n\n### Update repo \n\nYou can update the repo files quite easily\n\nFirst update the submodules\n\n```bash\nnpm run update\n```\n\nThen commit the changes\nThen update common files\n\n```bash\nnpm run sync\n```\nThen you can run `yarn|pnpm`, commit changed files if any\n\n### Update readme \n```bash\nnpm run readme\n```\n\n### Update doc \n```bash\nnpm run doc\n```\n\n### Publish\n\nThe publishing is completely handled by `lerna` (you can add `-- --bump major` to force a major release)\nSimply run \n```shell\nnpm run publish\n```\n\n### modifying submodules\n\nThe repo uses https:// for submodules which means you won't be able to push directly into the submodules.\nOne easy solution is t modify `~/.gitconfig` and add\n```\n[url \"ssh://git@github.com/\"]\n\tpushInsteadOf = https://github.com/\n```\n\n\r\n[](#questions)\r\n\r\n\r\n[](#questions)\r\n\r\n## Questions\n\nIf you have any questions/issues/comments please feel free to create an issue or start a conversation in the [NativeScript Community Discord](https://nativescript.org/discord).\n\n\r\n[](#demos-and-development)\r\n\r\n## Demos and Development\n\n\n### Repo Setup\n\nThe repo uses submodules. If you did not clone with ` --recursive` then you need to call\n```\ngit submodule update --init\n```\n\nThe package manager used to install and link dependencies must be `pnpm` or `yarn`. `npm` wont work.\n\nTo develop and test:\nif you use `yarn` then run `yarn`\nif you use `pnpm` then run `pnpm i`\n\n**Interactive Menu:**\n\nTo start the interactive menu, run `npm start` (or `yarn start` or `pnpm start`). This will list all of the commonly used scripts.\n\n### Build\n\n```bash\nnpm run build.all\n```\nWARNING: it seems `yarn build.all` wont always work (not finding binaries in `node_modules/.bin`) which is why the doc explicitly uses `npm run`\n\n### Demos\n\n```bash\nnpm run demo.[ng|react|svelte|vue].[ios|android]\n\nnpm run demo.svelte.ios # Example\n```\n\nDemo setup is a bit special in the sense that if you want to modify/add demos you dont work directly in `demo-[ng|react|svelte|vue]`\nInstead you work in `demo-snippets/[ng|react|svelte|vue]`\nYou can start from the `install.ts` of each flavor to see how to register new demos \n\n\r\n[](#contributing)\r\n\r\n## Contributing\n\n### Update repo \n\nYou can update the repo files quite easily\n\nFirst update the submodules\n\n```bash\nnpm run update\n```\n\nThen commit the changes\nThen update common files\n\n```bash\nnpm run sync\n```\nThen you can run `yarn|pnpm`, commit changed files if any\n\n### Update readme \n```bash\nnpm run readme\n```\n\n### Update doc \n```bash\nnpm run doc\n```\n\n### Publish\n\nThe publishing is completely handled by `lerna` (you can add `-- --bump major` to force a major release)\nSimply run \n```shell\nnpm run publish\n```\n\n### modifying submodules\n\nThe repo uses https:// for submodules which means you won't be able to push directly into the submodules.\nOne easy solution is t modify `~/.gitconfig` and add\n```\n[url \"ssh://git@github.com/\"]\n\tpushInsteadOf = https://github.com/\n```\n\r\n[](#questions)\r\n\r\n## Questions\n\nIf you have any questions/issues/comments please feel free to create an issue or start a conversation in the [NativeScript Community Discord](https://nativescript.org/discord).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnativescript-community%2Fui-mapbox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnativescript-community%2Fui-mapbox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnativescript-community%2Fui-mapbox/lists"}