{"id":13749738,"url":"https://github.com/hansemannn/titanium-googlemaps","last_synced_at":"2025-09-06T21:30:41.655Z","repository":{"id":2005561,"uuid":"44295912","full_name":"hansemannn/titanium-googlemaps","owner":"hansemannn","description":"🗺 Use the Google Maps SDK in Titanium","archived":false,"fork":false,"pushed_at":"2025-05-24T12:54:43.000Z","size":831041,"stargazers_count":87,"open_issues_count":2,"forks_count":25,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-05-24T13:53:53.947Z","etag":null,"topics":["google-maps","google-maps-api","ios","javascript","maps","native","tidev","titanium"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hansemannn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","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":"hansemannn"}},"created_at":"2015-10-15T05:34:00.000Z","updated_at":"2024-07-30T21:27:47.000Z","dependencies_parsed_at":"2024-08-03T07:13:55.050Z","dependency_job_id":null,"html_url":"https://github.com/hansemannn/titanium-googlemaps","commit_stats":null,"previous_names":[],"tags_count":70,"template":false,"template_full_name":null,"purl":"pkg:github/hansemannn/titanium-googlemaps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2Ftitanium-googlemaps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2Ftitanium-googlemaps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2Ftitanium-googlemaps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2Ftitanium-googlemaps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hansemannn","download_url":"https://codeload.github.com/hansemannn/titanium-googlemaps/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hansemannn%2Ftitanium-googlemaps/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273965057,"owners_count":25199190,"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","status":"online","status_checked_at":"2025-09-06T02:00:13.247Z","response_time":2576,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["google-maps","google-maps-api","ios","javascript","maps","native","tidev","titanium"],"created_at":"2024-08-03T07:01:11.285Z","updated_at":"2025-09-06T21:30:41.082Z","avatar_url":"https://github.com/hansemannn.png","language":"Objective-C","readme":"# Native GoogleMaps iOS SDK in Appcelerator Titanium\n\n[![License](http://hans-knoechel.de/shields/shield-license.svg?v=2)](./LICENSE)  [![Contact](http://hans-knoechel.de/shields/shield-twitter.svg?v=2)](http://twitter.com/hansemannnn)\n\n\u003cimg width=\"1094\" src=\"https://s20.directupload.net/images/240422/48blkzia.jpg\"\u003e\n\n## Summary\n\nTi.GoogleMaps is an open-source project to support the Google Maps iOS-SDK in Appcelerator's Titanium Mobile. The module currently supports the following API's:\n\n- [x] Map View\n- [x] Annotations\n- [x] Tile overlay\n- [x] Polygon overlay\n- [x] Polyline overlay\n- [x] Circle overlay\n- [x] Autocompletion dialog\n- [x] Clustering\n- [x] Directions\n- [x] Heatmap Layers\n- [x] All delegates (exposed as events)\n\n## Requirements\n\n  - Titanium 10.0.0+\n  - Minimum Deployment Target iOS 13+\n\n## Download, Setup and Build\n\n### Download\n\n  * [Stable release](https://github.com/hansemannn/titanium-googlemaps/releases)\n  * [![gitTio](http://hans-knoechel.de/shields/shield-gittio.svg)](http://gitt.io/component/ti.googlemaps)\n\n### Setup\n\n#### Add to your Project\n\nUnpack the module and place it inside the `modules/iphone/` folder of your project.\nEdit the modules section of your `tiapp.xml` file to include this module:\n```xml\n\u003cmodules\u003e\n    \u003cmodule platform=\"iphone\"\u003eti.googlemaps\u003c/module\u003e\n\u003c/modules\u003e\n```\n\n#### Initialize with your API Key\n\nInitialize the module by setting the Google Maps API key you can get from [here](https://developers.google.com/maps/signup).\n```js\nconst maps = require('ti.googlemaps');\nmaps.setAPIKey('\u003cYOUR_GOOGLE_MAPS_API_KEY\u003e');\n```\n\n#### Use Cross-Platform with Android\n\nIf you want to use this moduel as a replacement for Ti.Map  on iOS, here is how you can have 100 % parity:\n1. Create a file called `maps.js` in `app/lib/` (Alloy) or `Resources/` (Classic) with the following content\n```js\nif (Ti.Platform.osname === 'iphone' || Ti.Platform.osname === 'ipad') {\n  module.exports = TiMap = require('ti.googlemaps');\n} else {\n  module.exports = TiMap = require('ti.map');\n}\n```\n2. In your controllers, import / require the maps instance like before:\n```\n// ES6+ (recommended)\nimport TiMap from 'maps'\n\n// ES5\nconst TiMap = require('maps');\n```\n3. (optional) You can even use it in Alloy:\n```xml\n\u003cView module=\"maps\" method=\"createView\" id=\"mapView\" /\u003e\n```\n\nThat's it!\n\n### Build\n\nIf you want to build the module from the source, you need to check some things beforehand:\n- Set the `TITANIUM_SDK_VERSION` inside the `ios/titanium.xcconfig` file to the Ti.SDK version you want to build with.\n- Build the project with `appc run -p ios --build-only`\n- Check the [releases tab](https://github.com/hansemannn/titanium-googlemaps/releases) for stable pre-packaged versions of the module\n\n## Features\n\n### Map View\n\nA map view creates the view on which annotations and overlays can be added to. You can see all possible events in the demo app.\nIn addition, you can specify one of the following constants to the `mapType` property:\n - `MAP_TYPE_NORMAL`\n - `MAP_TYPE_HYBRID`\n - `MAP_TYPE_SATELLITE`\n - `MAP_TYPE_TERRAIN`\n - `MAP_TYPE_NONE`\n\n```js\nconst mapView = maps.createView({\n    mapType: maps.MAP_TYPE_TERRAIN,\n    indoorEnabled: true, // shows indoor capabilities (see \"Indoor Navigation\" section)\n    indoorPicker: true, // shows the vertical floor level (see \"Indoor Navigation\" section)\n    compassButton: true, // shows the compass (top/right) when bearing is non-zero\n    myLocationEnabled: true, // default: false\n    myLocationButton: true, // shows the default My location button\n    region: { // Camera center of the map\n        latitude: 37.368122,\n        longitude: -121.913653,\n        zoom: 10, // EITHER: Zoom in points\n        latitudeDelta: 0.1, longitudeDelta: 0.1, // OR: LAT/LONG-delta\n        bearing: 45, // orientation measured in degrees clockwise from north\n        viewingAngle: 30 // measured in degrees\n    }\n});\n```\n\n#### Safe Area / iPhone X\n\nThe GoogleMaps SDK supports configuring the map-view for the iPhone X. Use the `paddingAdjustmentBehavior` to get\nor set the padding-adjustment-behavior and use one of the following constants:\n```\n/** 1. Always include the safe area insets in the padding. */\nPADDING_ADJUSTMENT_BEHAVIOR_ALWAYS\n\n/**\n* 2. When the padding value is smaller than the safe area inset for a particular edge, use the safe\n* area value for layout, else use padding.\n*/\nPADDING_ADJUSTMENT_BEHAVIOR_AUTOMATIC\n\n/**\n* 3. Never include the safe area insets in the padding. This was the behavior prior to version 2.5.\n*/\nPADDING_ADJUSTMENT_BEHAVIOR_NEVER\n```\n\n#### Map Events\n\nThe module supports all native delegates - exposed as events. These are:\n\n- [x] click - Can be an annotation, overlay or info-window. Use `clicksource` to determine.\n- [x] mapclick\n- [x] locationclick\n- [x] longclick\n- [x] poiclick\n- [x] regionchanged\n- [x] regionwillchange\n- [x] idle\n- [x] dragstart\n- [x] dragmove\n- [x] dragend\n- [x] complete\n\n\u003e Note: For annotations, the latitude, longitude and userData is returned, not the whole annotation proxy to keep the\n\u003e performance at it's best. If you want to identify an annotation, either use the generated UUID string in the `userData`\n\u003e or set an own key in the `userData` property of your annotation.\n\n#### Map Controls\n\n```js\nmapView.indoorEnabled = false;\nmapView.indoorPicker = true;\nmapView.compassButton = true;\nmapView.myLocationEnabled = false;\nmapView.myLocationButton = false;\nmapView.trafficEnabled = true; // default is false\n```\n\n#### Enable / Disable Gestures\n\n```js\nmapView.scrollGesture = true;\nmapView.zoomGestures = false;\nmapView.tiltGestures = true;\nmapView.rotateGestures = false;\nmapView.allowScrollGesturesDuringRotateOrZoom = false;\n```\n\n#### Get current zoom level\n\n```js\nconst currentZoom = mapView.zoomLevel;\n```\n\nNote: You can watch the `regionchanged` event to get real time updates about the zoom level change.\nSee the `event.zoom` property for details.\n\n#### Map Padding\n\n\u003e Note: The `mapInsets` property is deprecated since Ti.GoogleMaps 4.0.0 in favor this property to achieve better\nparity with Ti.Map and will be removed in future versions of the module.\n\n```js\nmapView.padding = { bottom:200 };\n```\n\n#### Map Style\n\n```js\n// Either a JSON-string\nmapView.mapStyle = 'JSON_STYLE_GOES_HERE';\n\n// Or a JSON-file\nmapView.mapStyle = 'mapStyle.json'\n```\nSee [this link](https://developers.google.com/maps/documentation/ios-sdk/hiding-features) for more infos on map styling.\n\n#### Map Location\n\n```\nmap.location = {\n  latitude: 37.368122,\n  longitude: -121.913653,\n  latitudeDelta: 0.2,\n  longitudeDelta: 0.2,\n  animate: true\n}\n```\n\n#### Animations\n\n##### Animate to a location\n\n```js\nmapView.animateToLocation({\n    latitude: 36.368122,\n    longitude: -120.913653\n});\n```\n\n##### Animate to a zoom level:\n\n```js\nmapView.animateToZoom(5, 2000 /* Optional parameter to specify the duration (in ms) */);\n```\n\n##### Animate to a bearing:\n\n```js\nmapView.animateToBearing(45);\n```\n\n##### Animate to a viewing angle:\n\n```js\nmapView.animateToViewingAngle(30);\n```\n\n##### Take a snapshot:\n\n```js\nconst imageBlob = mapView.takeSnapshot({\n    width: 300,\n    width: 300\n});\n```\n\n##### Check if a location is currently visible on the map\n\n```js\nconst contains = mapView.containsCoordinate({ latitude: -13.37, longitude:  42.0 });\n```\n\n### Camera Update\n\nYou can perform camera updates to your map view instance by creating an instance of the `CameraUpdate` API:\n```js\nconst maps = require('ti.googlemaps');\nconst cameraUpdate = maps.createCameraUpdate();\n```\nBefore you can use the camera update, you must specify one of this actions:\n- [x] **zoomIn**\n```js\ncameraUpdate.zoomIn();\n```\n- [x] **zoomOut**\n```js\ncameraUpdate.zoomOut();\n```\n- [x] **zoom**\n```js\n// The second parameter is optional\ncameraUpdate.zoom(4, {\n    x: 100,\n    y: 100\n});\n```\n- [x] **enableMetalRenderer\n```js\nmaps.enableMetalRenderer();\n```\n- [x] **setTarget**\n```js\ncameraUpdate.setTarget({\n    latitude: 10.0,\n    longitude: 10.0,\n    zoom: 4 // optional\n});\n```\n- [x] **setCamera**\n```js\ncameraUpdate.setTarget({\n    latitude: 10.0,\n    longitude: 10.0,\n    zoom: 4,\n    bearing: 1,\n    viewingAngle: 45\n});\n```\n- [x] **fitBounds**\n```js\ncameraUpdate.fitBounds({\n    // IMPORTANT: Use either `padding` or `insets`, not both together\n    padding: 20,\n    insets: {top: 10, left: 10, bottom: 10, right: 10},\n    bounds: {\n        coordinate1: {\n            latitude: 10.0,\n            longitude: 10.0\n        },\n        coordinate2: {\n            latitude: 12.0,\n            longitude: 12.0\n        }\n    }\n});`\n```\n- [x] **scrollBy**\n```js\ncameraUpdate.scrollBy({\n    x: 100,\n    y: 100\n});\n```\n\nAfter creating the camera update, you can use it in one of the following methods:\n**moveCamera**\n```js\nmapView.moveCamera(cameraUpdate);\n```\n**animateWithCameraUpdate**\n```js\nmapView.animateWithCameraUpdate(cameraUpdate);\n```\n\n### Annotations\n\nAn annotation represents a location specified by at least a `title` and a `subtitle` property.\nIt can be added to a map view:\n\n```js\nconst annotation = maps.createAnnotation({\n    latitude: 37.368122,\n    longitude: -121.913653,\n    title: 'Appcelerator, Inc',\n    subtitle: '1732 N. 1st Street, San Jose',\n    pinColor: 'green',\n    image: 'pin.png',\n    touchEnabled: true, // Default: true\n    draggable: true, // Default: false\n    flat: true, // Default: false\n    opacity: 1,\n    zIndex: 1,\n    animationStyle: maps.APPEAR_ANIMATION_POP, // One of 'APPEAR_ANIMATION_NONE' (default), 'APPEAR_ANIMATION_POP' or 'APPEAR_ANIMATION_FADE'\n    rotation: 30, // measured in degrees clockwise from the default position\n    centerOffset: {\n        x: 0.5,\n        y: 0\n    },\n    groundOffset: {\n        x: 0.5,\n        y: 0\n    },\n    userData: {\n        id: 123,\n        custom_key: 'custom_value'\n    }\n});\nmapView.addAnnotation(annotation);\n```\n\nYou can get a list of all currently added annotations by using `mapView.annotations`;\n\nYou can set an info window of the annotation. Note that you have to specify a width / height for subviews,\notherwise the SDK will not set a proper frame for the subview:\n```js\nconst view = Ti.UI.createView({\n    backgroundColor: \"red\",\n    width: 200,\n    height: 30\n});\n\nconst label = Ti.UI.createLabel({\n    text: key,\n    width: 200,\n    height: 30,\n    color: '#fff',\n    textAlign: 'center'\n});\n\nview.add(label);\n\nconst annotation = maps.createAnnotation({\n    latitude: 37.4748624,\n    longitude: -122.1490817\n    infoWindow: view\n});\n```\n\nYou can update the location of an Annotation by using:\n```js\nannotation.updateLocation({\n    // Required\n    latitude: 36.368122,\n    longitude: -125.913653,\n\n    // Optional\n    animated: true,\n    duration: 1000 // in MS, default: 2000\n    opacity: 0.5,\n    rotation: 30 // in degrees, clockwise from the default position\n});\n```\n\nSince Ti.GoogleMaps 3.5.0, you can also set a custom view. Please note that you need to specify a valid size (width/height)\nfor each view-child of this properly, otherwise the view will not be visible. Example:\n```js\nconst maps = require(\"ti.googlemaps\");\nmaps.setAPIKey('\u003capi-key\u003e');\nconst win = Ti.UI.createWindow({\n    backgroundColor: '#fff'\n});\n\nconst mapView = maps.createView({\n    region: { // Camera center of the map\n        latitude: 37.368122,\n        longitude: -121.913653\n    }\n});\n\nconst label = Ti.UI.createLabel({\n    text: 'Ti',\n    width: Ti.UI.FILL, height: Ti.UI.FILL\n});\n\nconst view = Ti.UI.createView({\n    backgroundColor: 'red',\n    width: 30, height: 30\n});\n\nview.add(label);\n\nconst annotation = maps.createAnnotation({\n    latitude: 37.368122,\n    longitude: -121.913653,\n    title: 'Appcelerator, Inc',\n    customView: view\n});\n\nmapView.addAnnotation(annotation);\n\nwin.add(mapView);\nwin.open();\n```\n\nYou also can add multiple annotations as well as remove annotations again:\n```js\nmapView.addAnnotations([anno1,anno2,anno3]);\nmapView.removeAnnotation(anno4);\n```\n\nUse a module-generated custom pin to improve performance by decrease crossing the bridge\nand retaining Titanium proxies natively. Compared to `image`, you don't pass a blob but only a file\nreference and compared to `customView`, you don't have to pass JS proxies to the module:\n```js\nconst annotation = maps.createAnnotation({\n    latitude: 37.368122,\n    longitude: -121.913653,\n    customIcon: { title: '3+', image: '/images/pin.png', tintColor: 'red', textColor: 'white' }\n});\n```\n\nRemove Annotations by passing an array of Annotations:\n```js\nmapView.removeAnnotations([anno1,anno2,anno3]);\n```\nRemove all annotations (one shot):\n```js\nmapView.removeAllAnnotations();\n```\n\nYou can select and deselect annotations, as well as receive the currently selected annotation:\n```js\nmapView.selectAnnotation(anno1); // Select\nmapView.deselectAnnotation(); // Deselect\nconst selectedAnnotation = mapView.getSelectedAnnotation(); // Selected annotation, null if no annotation is selected\n```\n\n### Heatmap Layer\nUse heatmaps-layers in your map-views by providing weighted data and designated gradient-colors.\n\n```js\n// Import data\nconst stations = JSON.parse(Ti.Filesystem.getFile('police_stations.json').read());\nconst data = [];\n\n// Map data to an array of latitude/longitude/intensity objects\nfor (const i = 0; i \u003c stations.length; i++) {\n  const station = stations[i];\n\n  data.push({\n    latitude: station.lat,\n    longitude: station.lng,\n    intensity: 1.0\n  });\n}\n\n// Create a new heatmap-layer\nconst heatmap = maps.createHeatmapLayer({\n  weightedData: data,\n  radius: 80,\n  opacity: 0.8,\n  gradient: {\n    colors: [ 'green', 'red' ],\n    startPoints: [ 0.2, 1.0 ],\n    colorMapSize: 256\n  }\n});\n\n// Add the layer to your map-view\nmapView.addHeatmapLayer(heatmap);\n```\n\n### Autocomplete Dialog\n\nA autocomplete dialog can be opened modally to search for places in realtime. A number of events\nhelps to work with partial results and final selections.\n\nThe whole dialog can be styled (like in the following example) and the default native theming is light.\n\n```js\nconst dialog = GoogleMaps.createAutocompleteDialog({\n    tableCellBackgroundColor: '#333',\n    tableCellSeparatorColor: '#444',\n    primaryTextColor: '#fff',\n    primaryTextHighlightColor: 'blue',\n    tintColor: 'blue'\n});\n\n// You need a Google Places API key from the Google Developer Console\n// This is not the same one like your Google Maps API key\ndialog.configure('\u003cYOUR_GOOGLE_PLACES_API_KEY\u003e');\n\ndialog.open();\n```\n\n#### Autocomplete Events\n\n- [x] success\n- [x] error\n- [x] cancel\n\n### Overlays\n\nOverlays can be added to the map view just like annotations. The module supports the methods `addPolygon`, `addPolyline` and `addCircle` to add overlays and `removePolygon`, `removePolyline` and `removeCircle` to remove them.\n\n#### Polyline\n\nA polyline is a shape defined by its `points` property. It needs at least 2 points to draw a line.\n\n```js\nconst polyline = maps.createPolyline({\n    points: [ { // Can handle both object and array\n        latitude: -37.81319,\n        longitude: 144.96298\n    }, [ -31.95285, 115.85734 ] ], // Important: The longitude is at index 0 and the latitude at index 1\n    strokeWidth: 3, // Default: 1\n    strokeColor: '#f00'  // Default: Black (#000000),\n    title: 'My Polyline',\n    zIndex: 10,\n    tappable: true\n});\nmapView.addPolyline(polyline);\n```\n\nYou can get a list of all currently added polylines by using `mapView.polylines`.\n\nYou can also set a stamp-styled polyline by setting a dots image:\n```js\nmaps.dotsImage = 'images/my_icon.png';\n```\n\n##### Rounded Polylines\n\nIf you want rounded polylines (e.g. for simulating a flight direction), you can use the following method to draw the line:\n\n```js\n$.mapView.drawRoundedPolylineBetweenCoordinates({\n    coordinates: [ { latitude: 0.0, longitude: 0.0 }, { latitude: 1.0, longitude: 1.0 } ],\n    options: {} // Unused so far\n});\n```\n\n#### Polygon\n\nA polygon is a shape defined by its `points` property. It behaves similiar to a polyline, but is meant to close its area automatically and also supports the `fillColor` property.\n\n```js\nconst polygon = maps.createPolygon({\n    points: [ { // Can handle both object and array\n        latitude: -37.81819,\n        longitude: 144.96798\n    }, [ -31.95285, 115.85734 ] ],\n    strokeWidth: 3,\n    fillColor: 'yellow', // Default: Blue (#0000ff)\n    strokeColor: 'green',\n    title: 'My Polygon',\n    holes: [ {\n        latitude: -32.95785,\n        longitude: 115.86234\n    }, [ -32.95785, 115.86234 ] ], // Important: The longitude is at index 0 and the latitude at index 1.\n                                   // This has been changed in v6.1.2 of the module to align with the other APIs!\n    zIndex: 10\n});\nmapView.addPolygon(polygon);\n```\n\nYou can get a list of all currently added polygons by using `mapView.polygons`;\n\n#### Circle\n\nA circle is a shape defined by the `center` property to specify its location as well as the `radius` in meters.\n\n```js\nconst circle = maps.createCircle({\n    center: [ -32.9689, 151.7721 ], // Can handle object or array. Important: The longitude is at index 0 and the latitude at index 1.\n    radius: 500 * 1000, // 500 km, Default: 0\n    fillColor: 'blue', // Default: transparent\n    strokeWidth: 3,\n    strokeColor: 'orange'\n    title: 'My Circle',\n    zIndex: 10\n});\nmapView.addCircle(circle);\n```\n\nYou can get a list of all currently added circles by using `mapView.circles`;\n\n### Clustering\n\nYou can cluster multiple items by using the Clustering API.\n\nFirst, create a few cluster items using the `ClusterItem`:\n```js\nconst items = [];\n\nconst clusterItem = maps.createClusterItem({\n    // Required\n    latitude: 37.368122,\n    longitude: -121.913653,\n\n    // Optional - for now only this three properties available\n    title: 'My Annotation',\n    subtitle: 'Hello World!',\n    icon: 'marker.png' // either a String, Ti.Blob or Ti.File\n});\n\n// Create some more items here ...\n\nitems.push(clusterItem);\n```\nThen add the cluster items to a map:\n```js\nmapView.addClusterItems(items);\n```\nFinally, call `cluster()` to generate a new cluster:\n```js\nmapView.cluster();\n```\nYou are all set! Optionally, you can also set your own cluster ranges and define custom\nimages for each cluster range in your `mapView` instance:\n```js\nconst mapView = maps.createView({\n    clusterConfiguration: {\n        ranges: [ 10, 50, 100, 200, 500 ],\n        rangeBackgrounds: [\n            'buckets/m1.png',\n            'buckets/m2.png',\n            'buckets/m3.png',\n            'buckets/m4.png',\n            'buckets/m5.png'\n        ],\n        minimumClusterSize: 4,\n        maximumClusterZoom: 20,\n        animationDuration: 0.5\n    },\n    region: {\n        latitude: 37.368122,\n        longitude: -121.913653,\n    }\n});\n```\n\nTo remove cluster-items or clear the whole cluster, use the following methods:\n```js\n// Remove a single cluster-item\nmapView.removeClusterItem(clisterItem);\n\n// Clear the whole cluster\nmapView.clearClusterItems();\n```\n\nUse the `clusterclick` and `clusteritemclick` events on your map view instance\nto receive infos about your current cluster or cluster item.\n\n### Tile Layers\n\nYou can create URL-based tile layers that use the x / y / z (zoom level) pattern to determine the location pattern:\n```js\nconst tile = maps.createTile({\n    // Required\n\t  // z is for zoom level\n    url: \"http://c.tile.openstreetmap.org/{z}/{x}/{y}.png\",\n\n    // Optional\n    userAgent: \"Titanium rocks!\",\n    zIndex: 100,\n    size: 200,\n    opacity: 1,\n    fadeIn: true\n});\n\n// Clear previous tile cache from this URL\ntile.clearTileCache();\n\n// Add tile\nmapView.addTile(tile);\n\n// Remove tile\nmapView.removeTile(tile);\n```\nYou can also request a tile image for a specified x/y/zoom position:\n```js\nconst tile = maps.createTile({\n    url: \"http://c.tile.openstreetmap.org/{z}/{x}/{y}.png\",\n});\n\ntile.addEventListener('receivetile', event =\u003e {\n    Ti.API.info(`Received new tile at ${event.tile.x}x${event.tile.y}`);\n    Ti.API.info(event);\n\n    // Add tile image to a view or process it somewhere else\n    // win.add(Ti.UI.createImageView({ image: event.tile.image }));\n});\n\ntile.requestTile({\n    x: 200,\n    y: 200,\n    zoom: 3\n});\n```\n\nFor more information on Tile Layers: https://developers.google.com/maps/documentation/ios-sdk/tiles\n\nIn future releases you will also be able to specify local images, but that is not scheduled so far.\n\n### Renderer\n\nUsing Ti.GoogleMaps 3.8.0 and later, you are able to render '.geojson' and '.kml' files inside your map\nby using the `Renderer` API. In can be instantiated by using the following constructor:\n```js\nconst renderer = map.createRenderer({\n    file: 'example.geojson'\n    mapView: mapView\n});\n```\nThere are two methods `render` and `clear` available:\n```js\n// Renders the geometries\nrenderer.render();\n\n// Removes the geometries\nrenderer.clear();\n```\n\n### Reverse Geocoder\nUse the reverse geocoder to search a location based on a `latitude` and `longitude`:\n```js\nmaps.reverseGeocoder(36.368122, -120.913653, event =\u003e {\n    alert('Address found!');\n\n    Ti.API.info(event.places);\n});\n```\n\n### Indoor Navigation\n\nThere are a number of special API's to deal with indoor-navigtion in GoogleMaps. Inside a `View` instance,\nyou can enabled indoor-navigation by setting `indoorEnabled` to `true`. To show the the vertical floor levels\nin your map-instance, set `indoorPicker` to `true`.\n\nTo receive the indoor-display, use the `indoorDisplay` getter,\nwhich has the following events to be notified when the indoor-navigation changes:\n\n- [x] `didChangeActiveBuilding` (Raised when the activeBuilding has changed)\n  - `defaultLevelIndex` (Array of GMSIndoorLevel describing the levels which make up the building)\n  - `isUnderground` (Index in the levels array of the default level)\n  - `levels` (If `true`, the building is entirely underground and supports being hidden)\n\n- [x] `didChangeActiveLevel` (Raised when the activeLevel has changed)\n  - `name` (Localized display name for the level, e.g. \"Ground floor\")\n  - `shortName` (Localized short display name for the level, e.g. \"1\")\n\nIn addition to the above events, you can also communicate with the indoor-display by receiving the `activeBuilding`\nand `activeLevel` properties. Finally, when receiving the floor-level inside the `level` property of the\n`didChangeActiveBuilding` event, you can set the `activeLevel` property as well, to change the currently active\nfloor-level.\n\n### Directions\n\nUse the Directions API to calculate advanced directions:\n\n```js\nmaps.getDirections({\n    origin: 'Mountain View, CA',\n    destination: 'San Francisco, CA',\n    success: event =\u003e {\n        Ti.API.info(event.routes);\n    },\n    error: event =\u003e {\n        Ti.API.error(`Error: ${event.error}`);\n    },\n    waypoints: [ 'Cupertino, CA', 'via:Sunnyvale, CA' ] // Optional\n});\n```\nThe polyline points will be received encoded:\n```js\n\"polyline\": {\n    \"points\": \"a}dcF~nchVPLXLHQhAsCDKzAyDPe@fAqC`@aAh@sARc@pCoHJUj@yAj@{AL]`@cAd@iAbAiCnC_HjAsCvAqDL_@l@mB`@sA^kAJ[h@aBPi@DSJWDMHSFS@GXaABIBI\\\\eAHW?ATy@HSPo@\"\n}\n```\nTo decode the polyline points, use the `maps.decodePolylinePoints(points)` utility method or [this utility](https://github.com/mapbox/polyline).\n\nNote that this is not officially supported in the Google Maps iOS SDK. It has been exposed\nby using the REST-API in combination with the `NSURLSession` API and the provided API key.\n\n### Geometry Utils\n\n#### `geometryContainsLocation`\n\nCheck whether or not a given geometry list contains a given location.\n\n```js\nconst geometryContainsLocation = maps.geometryContainsLocation({\n    location: { latitude: 1, longitude: -1 },\n    points: [ {\n        latitude: 37.368122,\n        longitude: -121.234\n    }, {\n        latitude: 35.368122,\n        longitude: -119.234\n    } ]\n});\n\nconsole.log(`geometryContainsLocation: ${geometryContainsLocation}`);\n```\n\n#### `geometryDistanceBetweenPoints`\n\nGet the geometry distance between two given points in meters.\nThe geodesic is included in the calculation.\n\n```js\nconst location1 = { latitude: 52.687489, longitude: 7.291130 };\nconst location2 = { latitude: 52.279911, longitude: 8.047179 };\n\nconst geometryDistanceBetweenPoints = maps.geometryDistanceBetweenPoints(location1, location2);\n```\n\n#### `coordinateForPoint`\n\nReturns the coordinate pair for the given screen point\n\n```js\nconst coordinate = maps.coordinateForPoint({\n  x: point.x,\n  y: point.y,\n});\n```\n\n### Google License Info\n\nGoogle requires you to link the Open Source license somewhere in your app.\nUse the following API to receive the Google Maps license:\n\n```js\nconst license = maps.getOpenSourceLicenseInfo();\n```\n\n## Example\nFor a full example, check the demos in `example/app.js` and `example/clustering.js`.\n\n## Author\nHans Knöchel ([@hansemannnn](https://twitter.com/hansemannnn) / [Web](http://hans-knoechel.de))\n\n## License\nApache 2.0\n\n## Contributing\nCode contributions are greatly appreciated, please submit a new [Pull-Request](https://github.com/hansemannn/titanium-google-maps/pull/new/master)!\n","funding_links":["https://github.com/sponsors/hansemannn"],"categories":["Objective-C"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhansemannn%2Ftitanium-googlemaps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhansemannn%2Ftitanium-googlemaps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhansemannn%2Ftitanium-googlemaps/lists"}