A basic port of ArcGIS for React Native. Handles basemap URLs, map recentering, Callout views (iOS only for now), drawing/moving/updating graphics onto the map, routing, and single tap listeners.
import ArcGISMapView from 'react-native-arcgis-mapview'
...
render() {
return(
...
<ArcGISMapView ref={mapView => this.mapView = mapView}
// your props here
/>
)
}
...
yarn add react-native-arcgis-mapview
or npm install react-native-arcgis-mapview
Then run react-native link react-native-arcgis-mapview
First off, make sure your minSdk version is 19 and your targetSdk is at least 28 (ArcGIS requires a minimum SDK level of 19). You can easily set these by modifying your Project build.gradle, within buildscript -> ext.
Inside your Project Gradle file, inside of allProjects, and within the repositories tag, add the following:
maven {
url 'https://esri.bintray.com/arcgis'
}
Then, inside your App Gradle file, if your app does not already have Java 8 Support (ArcGIS Requires this from 100.4 onwards), add the following line inside the android bracket:
compileOptions {
sourceCompatibility 1.8
targetCompatibility 1.8
}
That's it. Your project should build.
iOS is a bit trickier. Create a podfile in your iOS directory with the following contents:
platform :ios, '11.0'
target 'Example' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
rn_path = '../node_modules/react-native'
# See http://facebook.github.io/react-native/docs/integration-with-existing-apps.html#configuring-cocoapods-dependencies
pod 'yoga', path: "#{rn_path}/ReactCommon/yoga/yoga.podspec"
pod 'React', path: rn_path, subspecs: [
'Core',
'CxxBridge',
'DevSupport',
'RCTActionSheet',
'RCTAnimation',
'RCTGeolocation',
'RCTImage',
'RCTLinkingIOS',
'RCTNetwork',
'RCTSettings',
'RCTText',
'RCTVibration',
'RCTWebSocket',
], :modular_headers => true
# React Native third party dependencies podspecs
pod 'DoubleConversion', :podspec => "#{rn_path}/third-party-podspecs/DoubleConversion.podspec"
pod 'glog', :podspec => "#{rn_path}/third-party-podspecs/glog.podspec"
# If you are using React Native <0.54, you will get the following error:
# "The name of the given podspec `GLog` doesn't match the expected one `glog`"
# Use the following line instead:
#pod 'GLog', :podspec => "#{rn_path}/third-party-podspecs/GLog.podspec"
pod 'Folly', :podspec => "#{rn_path}/third-party-podspecs/Folly.podspec"
pod 'RNArcGISMapView', :path => "../node_modules/react-native-arcgis-mapview/ios"
end
# The following is needed to ensure the "archive" step works in XCode.
# It removes React from the Pods project, as it is already included in the main project.
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.name == "React"
target.remove_from_project
end
end
end
If you already have a podfile, this is the key line you need to add:
pod 'RNArcGISMapView', :path => "../node_modules/react-native-arcgis-mapview/ios"
If you don't have swift implemented into your project, open your project directory and make a new Swift file. Name it whatever you want, it doesn't matter. Upon making this file, XCode should ask if you want to create a bridging header. If you plan on using Swift in your project, selecte 'Create Header'; otherwise, select no thanks. Then, open your project file and ensure your iOS Project targets iOS 11 or above and the Swift Language Version is set to 'Swift 4.2.' Clean, rebuild, and you should be good to go.
A license is not required to develop and test. However, to release your app, you must provide a license. See here for iOS or here for Android for more information on how to get a license.
Once you have one, it's easy to add it into your project. In your App.js (or wherever you initialize your app)
import { setLicenseKey } from 'react-native-arcgis-mapview';
export default class App extends Component {
...
constructor(props){
setLicenseKey('your_key');
...
}
...
}
Prop Name | Type | Description | Default |
---|---|---|---|
initialMapCenter | Object Array | Specifies the initial center of the map. Objects within the array must have both a latitude and longitude values. Including a single point will center around that point, while including multiple points will center around a polygon containing those points. | [{latitude: 36.244797, longitude: -94.148060}] |
recenterIfGraphicTapped | Boolean | If true, the map will recenter if a graphic is tapped on. | false |
basemapUrl | String | A URL that links to an ArcGIS Online map with your style. A description on how to get this working can be found below. Here's an example of one that works. | '' |
routeUrl | String | A URL that refers to an ArcGIS routing service. See routing below for more information. | |
minZoom | Double | A value that represents the minimum level in which a user can zoom out. For example, 70000000 is about continent level zoom. | 0 |
maxZoom | Double | A value that represents the maximum level in which a user can zoom in. For example, 10000 is about building level zoom. | 0 |
rotateEnabled | Boolean | If false, prevents the user from rotating the map. | true |
Just follow these steps to get your basemap up and running.
Callback Name | Parameters | Description |
---|---|---|
onSingleTap | { points: { mapPoint: {latitude: Number, longitude: Number}, screenPoint: {x: Number, y: Number}, },graphicReferenceId: String?, } |
A callback that runs whenever the map is tapped once. A graphics ID is returned if a graphic was tapped on. |
onOverlayWasAdded | { referenceId: String } |
Called when overlay is added. |
onOverlayWasRemoved | { referenceId: String } |
Called when overlay is removed. |
onOverlayWasModified | { referenceId: String, action: String, success: Boolean, errorMessage: String? } |
Fires when an overlay was modified. |
onMapDidLoad | { success: Boolean, errorMessage: String? } |
Executed when the map finishes loading or runs into an error. |
onRoutingStatusUpdate | isRouting: Boolean |
Returns true or false whenever the app begins or ends a routing call. Useful for telling the user when a routing action is happening in the background. |
Method Name | Parameters | Description |
---|---|---|
showCallout | { point: {latitude, longitude} , title: String?, text String?, shouldRecenter: Boolean? } |
(iOS Only) Creates a callout popup with a title and description at the given point. |
recenterMap | [ point: {latitude, longitude}, point, ... ] |
Recenters the map around the given point(s). |
addGraphicsOverlay | {pointGraphics: [graphicId: String, graphic: Image]?, referenceId: String, points: [Point] } |
Adds a graphics overlay with the given points. See below for more information. |
removeGraphicsOverlay | { overlayId: String } |
Removes the graphics overlay with the given ID. |
addPointsToOverlay | { overlayReferenceId: String, points: [Point] } |
Adds points to the overlay with the given overlayReferenceId. |
removePointsFromOverlay | { overlayReferenceId: String, referenceIds: [String] } |
Removes points from the overlay with the given overlayReferenceID. The reference ID array are the IDs of the points you wish to remove. |
updatePointsOnOverlay | { overlayReferenceId: String, updates: [Point], animated: Boolean } |
Updates points on a given overlay. All properties within an individual Point object are optional, though latitude and longitude must both be provided if you are updating either one. Animated controls whether or not the app should animate the transition from one point/rotation to another. Make sure each update is spaced about 500ms apart. |
routeGraphicsOverlay | { overlayReferenceId: String, excludeGraphics: [String]?, routeColor: String? } |
Routes a one-way route from all points within the overlay associated with the overlayReferenceId. You can exclude points by ID by placing their IDs inside the excludeGraphics array. See below for more info. |
getRouteIsVisible | {callback: Callback(Boolean)} |
Returns the visibility of the route layer and passes it through a callback. |
setRouteIsVisible | { routeIsVisible: Boolean } |
Toggles the visiblity of the routing layer. |
Above, the Point object was referenced as 'Point.' The Point object is structured as follows:
point: {
latitude: Number,
longitude: Number,
rotation: Number? = 0,
referenceId: String,
graphicId: String?,
}
When defining graphics, use the following format:
import { Image } from 'react-native';
...
pointGraphics: [
{graphicId: 'graphicId', graphic: Image.resolveAssetSource(require('path_to_your_local_image')) },
// Repeat for as many graphics as you'd like
]
...
{
pointGraphics: [
{graphicId: 'normalPoint', graphic: Image.resolveAssetSource(require('./src/normalpoint.png'))},
{graphicId: 'personPoint', graphic: Image.resolveAssetSource(require('./src/personpoint.png'))},
{graphicId: 'planePoint', graphic: Image.resolveAssetSource(require('./src/planepoint.png'))},
],
referenceId: 'graphicsOverlay',
points: [{
latitude: 45.512230,
longitude: -122.658722,
rotation: 0,
referenceId: 'Portland',
graphicId: 'normalPoint',
},{
latitude: 38.907192,
longitude: -77.036873,
rotation: 0,
referenceId: 'Washington, D.C.',
graphicId: 'personPoint',
},{
latitude: 39.739235,
longitude: -104.990250,
rotation: 0,
referenceId: 'movingImage',
graphicId: 'planePoint',
},
]
}
For routing to work, you must also pass in a routeUrl prop with a reference to a routing service. Check the Choosing a routing data source section of this Esri Article for information on how to make one.
Once you have a routing URL, try calling routeGraphicsOverlay
to see if your routing service has been configuired correctly. If it doesn't work, chances are your URL doesn't have the necessary permissions set. Make sure it has public access. Note that routing is an asynchronous task, and for longer routes, this may take a moment. Use the onRoutingStatusUpdate
callback to create any UI you may need to inform the user that a route calculation is currently taking place.
The biggest gotcha, however, is that routing uses up ArcGIS Online Credits. You are given 50 free credits a month; however, you must buy additional credits to continue routing. Make sure your ArcGIS Online account has sufficient credits before release.
Library Copyright 2019 David Galindo
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.
ArcGIS SDK for Android and iOS Copyright 2019 Esri.