752 lines
20 KiB
JavaScript
752 lines
20 KiB
JavaScript
import PropTypes from 'prop-types';
|
||
import React from 'react';
|
||
import {
|
||
EdgeInsetsPropType,
|
||
Platform,
|
||
Animated,
|
||
requireNativeComponent,
|
||
NativeModules,
|
||
ColorPropType,
|
||
findNodeHandle,
|
||
ViewPropTypes,
|
||
View,
|
||
} from 'react-native';
|
||
import MapMarker from './MapMarker';
|
||
import MapPolyline from './MapPolyline';
|
||
import MapPolygon from './MapPolygon';
|
||
import MapCircle from './MapCircle';
|
||
import MapCallout from './MapCallout';
|
||
import MapUrlTile from './MapUrlTile';
|
||
import MapLocalTile from './MapLocalTile';
|
||
import AnimatedRegion from './AnimatedRegion';
|
||
import {
|
||
contextTypes as childContextTypes,
|
||
getAirMapName,
|
||
googleMapIsInstalled,
|
||
createNotSupportedComponent,
|
||
} from './decorateMapComponent';
|
||
import * as ProviderConstants from './ProviderConstants';
|
||
|
||
const MAP_TYPES = {
|
||
STANDARD: 'standard',
|
||
SATELLITE: 'satellite',
|
||
HYBRID: 'hybrid',
|
||
TERRAIN: 'terrain',
|
||
NONE: 'none',
|
||
MUTEDSTANDARD: 'mutedStandard',
|
||
};
|
||
|
||
const GOOGLE_MAPS_ONLY_TYPES = [
|
||
MAP_TYPES.TERRAIN,
|
||
MAP_TYPES.NONE,
|
||
];
|
||
|
||
const viewConfig = {
|
||
uiViewClassName: 'AIR<provider>Map',
|
||
validAttributes: {
|
||
region: true,
|
||
},
|
||
};
|
||
|
||
// if ViewPropTypes is not defined fall back to View.propType (to support RN < 0.44)
|
||
const viewPropTypes = ViewPropTypes || View.propTypes;
|
||
|
||
const propTypes = {
|
||
...viewPropTypes,
|
||
/**
|
||
* When provider is "google", we will use GoogleMaps.
|
||
* Any value other than "google" will default to using
|
||
* MapKit in iOS or GoogleMaps in android as the map provider.
|
||
*/
|
||
provider: PropTypes.oneOf([
|
||
'google',
|
||
]),
|
||
|
||
/**
|
||
* Used to style and layout the `MapView`. See `StyleSheet.js` and
|
||
* `ViewStylePropTypes.js` for more info.
|
||
*/
|
||
style: viewPropTypes.style,
|
||
|
||
/**
|
||
* A json object that describes the style of the map. This is transformed to a string
|
||
* and saved in mayStyleString to be sent to android and ios
|
||
* https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource
|
||
* https://developers.google.com/maps/documentation/android-api/styling
|
||
*/
|
||
customMapStyle: PropTypes.array,
|
||
|
||
/**
|
||
* A json string that describes the style of the map
|
||
* https://developers.google.com/maps/documentation/ios-sdk/styling#use_a_string_resource
|
||
* https://developers.google.com/maps/documentation/android-api/styling
|
||
*/
|
||
customMapStyleString: PropTypes.string,
|
||
|
||
/**
|
||
* If `true` the app will ask for the user's location.
|
||
* Default value is `false`.
|
||
*
|
||
* **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in
|
||
* Info.plist to enable geolocation, otherwise it is going
|
||
* to *fail silently*!
|
||
*/
|
||
showsUserLocation: PropTypes.bool,
|
||
|
||
/**
|
||
* The title of the annotation for current user location. This only works if
|
||
* `showsUserLocation` is true.
|
||
* There is a default value `My Location` set by MapView.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
userLocationAnnotationTitle: PropTypes.string,
|
||
|
||
/**
|
||
* If `false` hide the button to move map to the current user's location.
|
||
* Default value is `true`.
|
||
*
|
||
* @platform android
|
||
*/
|
||
showsMyLocationButton: PropTypes.bool,
|
||
|
||
/**
|
||
* If `true` the map will focus on the user's location. This only works if
|
||
* `showsUserLocation` is true and the user has shared their location.
|
||
* Default value is `false`.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
followsUserLocation: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` points of interest won't be displayed on the map.
|
||
* Default value is `true`.
|
||
*
|
||
*/
|
||
showsPointsOfInterest: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` compass won't be displayed on the map.
|
||
* Default value is `true`.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
showsCompass: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` the user won't be able to pinch/zoom the map.
|
||
* Default value is `true`.
|
||
*
|
||
*/
|
||
zoomEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` the user won't be able to pinch/rotate the map.
|
||
* Default value is `true`.
|
||
*
|
||
*/
|
||
rotateEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* If `true` the map will be cached to an Image for performance
|
||
* Default value is `false`.
|
||
*
|
||
*/
|
||
cacheEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* If `true` the map will be showing a loading indicator
|
||
* Default value is `false`.
|
||
*
|
||
*/
|
||
loadingEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* Loading background color while generating map cache image or loading the map
|
||
* Default color is light gray.
|
||
*
|
||
*/
|
||
loadingBackgroundColor: ColorPropType,
|
||
|
||
/**
|
||
* Loading indicator color while generating map cache image or loading the map
|
||
* Default color is gray color for iOS, theme color for Android.
|
||
*
|
||
*/
|
||
loadingIndicatorColor: ColorPropType,
|
||
|
||
/**
|
||
* If `false` the user won't be able to change the map region being displayed.
|
||
* Default value is `true`.
|
||
*
|
||
*/
|
||
scrollEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` the user won't be able to adjust the camera’s pitch angle.
|
||
* Default value is `true`.
|
||
*
|
||
*/
|
||
pitchEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* If `false` will hide 'Navigate' and 'Open in Maps' buttons on marker press
|
||
* Default value is `true`.
|
||
*
|
||
* @platform android
|
||
*/
|
||
toolbarEnabled: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean indicating whether on marker press the map will move to the pressed marker
|
||
* Default value is `true`
|
||
*
|
||
* @platform android
|
||
*/
|
||
moveOnMarkerPress: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean indicating whether the map shows scale information.
|
||
* Default value is `false`
|
||
*
|
||
*/
|
||
showsScale: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean indicating whether the map displays extruded building information.
|
||
* Default value is `true`.
|
||
*/
|
||
showsBuildings: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean value indicating whether the map displays traffic information.
|
||
* Default value is `false`.
|
||
*/
|
||
showsTraffic: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean indicating whether indoor maps should be enabled.
|
||
* Default value is `false`
|
||
*
|
||
* @platform android
|
||
*/
|
||
showsIndoors: PropTypes.bool,
|
||
|
||
/**
|
||
* A Boolean indicating whether indoor level picker should be enabled.
|
||
* Default value is `false`
|
||
*
|
||
* @platform android
|
||
*/
|
||
showsIndoorLevelPicker: PropTypes.bool,
|
||
|
||
/**
|
||
* The map type to be displayed.
|
||
*
|
||
* - standard: standard road map (default)
|
||
* - satellite: satellite view
|
||
* - hybrid: satellite view with roads and points of interest overlayed
|
||
* - terrain: topographic view
|
||
* - none: no base map
|
||
*/
|
||
mapType: PropTypes.oneOf(Object.values(MAP_TYPES)),
|
||
|
||
/**
|
||
* The region to be displayed by the map.
|
||
*
|
||
* The region is defined by the center coordinates and the span of
|
||
* coordinates to display.
|
||
*/
|
||
region: PropTypes.shape({
|
||
/**
|
||
* Coordinates for the center of the map.
|
||
*/
|
||
latitude: PropTypes.number.isRequired,
|
||
longitude: PropTypes.number.isRequired,
|
||
|
||
/**
|
||
* Difference between the minimun and the maximum latitude/longitude
|
||
* to be displayed.
|
||
*/
|
||
latitudeDelta: PropTypes.number.isRequired,
|
||
longitudeDelta: PropTypes.number.isRequired,
|
||
}),
|
||
|
||
/**
|
||
* The initial region to be displayed by the map. Use this prop instead of `region`
|
||
* only if you don't want to control the viewport of the map besides the initial region.
|
||
*
|
||
* Changing this prop after the component has mounted will not result in a region change.
|
||
*
|
||
* This is similar to the `initialValue` prop of a text input.
|
||
*/
|
||
initialRegion: PropTypes.shape({
|
||
/**
|
||
* Coordinates for the center of the map.
|
||
*/
|
||
latitude: PropTypes.number.isRequired,
|
||
longitude: PropTypes.number.isRequired,
|
||
|
||
/**
|
||
* Difference between the minimun and the maximum latitude/longitude
|
||
* to be displayed.
|
||
*/
|
||
latitudeDelta: PropTypes.number.isRequired,
|
||
longitudeDelta: PropTypes.number.isRequired,
|
||
}),
|
||
|
||
/**
|
||
* A Boolean indicating whether to use liteMode for android
|
||
* Default value is `false`
|
||
*
|
||
* @platform android
|
||
*/
|
||
liteMode: PropTypes.bool,
|
||
|
||
/**
|
||
* (Google Maps only)
|
||
*
|
||
* Padding that is used by the Google Map View to position
|
||
* the camera, legal labels and buttons
|
||
*
|
||
*/
|
||
mapPadding: EdgeInsetsPropType,
|
||
|
||
/**
|
||
* Maximum size of area that can be displayed.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
maxDelta: PropTypes.number,
|
||
|
||
/**
|
||
* Minimum size of area that can be displayed.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
minDelta: PropTypes.number,
|
||
|
||
/**
|
||
* Insets for the map's legal label, originally at bottom left of the map.
|
||
* See `EdgeInsetsPropType.js` for more information.
|
||
*/
|
||
legalLabelInsets: EdgeInsetsPropType,
|
||
|
||
/**
|
||
* Callback that is called once the map is fully loaded.
|
||
*/
|
||
onMapReady: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called continuously when the user is dragging the map.
|
||
*/
|
||
onRegionChange: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called once, when the user is done moving the map.
|
||
*/
|
||
onRegionChangeComplete: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when user taps on the map.
|
||
*/
|
||
onPress: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when user makes a "long press" somewhere on the map.
|
||
*/
|
||
onLongPress: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when user makes a "drag" somewhere on the map
|
||
*/
|
||
onPanDrag: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when a marker on the map is tapped by the user.
|
||
*/
|
||
onMarkerPress: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when a marker on the map becomes selected. This will be called when
|
||
* the callout for that marker is about to be shown.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
onMarkerSelect: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when a marker on the map becomes deselected. This will be called when
|
||
* the callout for that marker is about to be hidden.
|
||
*
|
||
* @platform ios
|
||
*/
|
||
onMarkerDeselect: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when a callout is tapped by the user.
|
||
*/
|
||
onCalloutPress: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when the user initiates a drag on a marker (if it is draggable)
|
||
*/
|
||
onMarkerDragStart: PropTypes.func,
|
||
|
||
/**
|
||
* Callback called continuously as a marker is dragged
|
||
*/
|
||
onMarkerDrag: PropTypes.func,
|
||
|
||
/**
|
||
* Callback that is called when a drag on a marker finishes. This is usually the point you
|
||
* will want to setState on the marker's coordinate again
|
||
*/
|
||
onMarkerDragEnd: PropTypes.func,
|
||
|
||
/**
|
||
* Minimum zoom value for the map, must be between 0 and 20
|
||
*/
|
||
minZoomLevel: PropTypes.number,
|
||
|
||
/**
|
||
* Maximum zoom value for the map, must be between 0 and 20
|
||
*/
|
||
maxZoomLevel: PropTypes.number,
|
||
|
||
};
|
||
|
||
class MapView extends React.Component {
|
||
constructor(props) {
|
||
super(props);
|
||
|
||
this.state = {
|
||
isReady: Platform.OS === 'ios',
|
||
};
|
||
|
||
this._onMapReady = this._onMapReady.bind(this);
|
||
this._onMarkerPress = this._onMarkerPress.bind(this);
|
||
this._onChange = this._onChange.bind(this);
|
||
this._onLayout = this._onLayout.bind(this);
|
||
}
|
||
|
||
getChildContext() {
|
||
return { provider: this.props.provider };
|
||
}
|
||
|
||
componentWillUpdate(nextProps) {
|
||
const a = this.__lastRegion;
|
||
const b = nextProps.region;
|
||
if (!a || !b) return;
|
||
if (
|
||
a.latitude !== b.latitude ||
|
||
a.longitude !== b.longitude ||
|
||
a.latitudeDelta !== b.latitudeDelta ||
|
||
a.longitudeDelta !== b.longitudeDelta
|
||
) {
|
||
this.map.setNativeProps({ region: b });
|
||
}
|
||
}
|
||
|
||
componentDidMount() {
|
||
const { isReady } = this.state;
|
||
if (isReady) {
|
||
this._updateStyle();
|
||
}
|
||
}
|
||
|
||
_updateStyle() {
|
||
const { customMapStyle } = this.props;
|
||
this.map.setNativeProps({ customMapStyleString: JSON.stringify(customMapStyle) });
|
||
}
|
||
|
||
_onMapReady() {
|
||
const { region, initialRegion, onMapReady } = this.props;
|
||
if (region) {
|
||
this.map.setNativeProps({ region });
|
||
} else if (initialRegion) {
|
||
this.map.setNativeProps({ initialRegion });
|
||
}
|
||
this._updateStyle();
|
||
this.setState({ isReady: true }, () => {
|
||
if (onMapReady) onMapReady();
|
||
});
|
||
}
|
||
|
||
_onLayout(e) {
|
||
const { layout } = e.nativeEvent;
|
||
if (!layout.width || !layout.height) return;
|
||
if (this.state.isReady && !this.__layoutCalled) {
|
||
const { region, initialRegion } = this.props;
|
||
if (region) {
|
||
this.__layoutCalled = true;
|
||
this.map.setNativeProps({ region });
|
||
} else if (initialRegion) {
|
||
this.__layoutCalled = true;
|
||
this.map.setNativeProps({ initialRegion });
|
||
}
|
||
}
|
||
if (this.props.onLayout) {
|
||
this.props.onLayout(e);
|
||
}
|
||
}
|
||
|
||
_onMarkerPress(event) {
|
||
if (this.props.onMarkerPress) {
|
||
this.props.onMarkerPress(event.nativeEvent);
|
||
}
|
||
}
|
||
|
||
_onChange(event) {
|
||
this.__lastRegion = event.nativeEvent.region;
|
||
if (event.nativeEvent.continuous) {
|
||
if (this.props.onRegionChange) {
|
||
this.props.onRegionChange(event.nativeEvent.region);
|
||
}
|
||
} else if (this.props.onRegionChangeComplete) {
|
||
this.props.onRegionChangeComplete(event.nativeEvent.region);
|
||
}
|
||
}
|
||
|
||
animateToRegion(region, duration) {
|
||
this._runCommand('animateToRegion', [region, duration || 500]);
|
||
}
|
||
|
||
animateToCoordinate(latLng, duration) {
|
||
this._runCommand('animateToCoordinate', [latLng, duration || 500]);
|
||
}
|
||
|
||
animateToBearing(bearing, duration) {
|
||
this._runCommand('animateToBearing', [bearing, duration || 500]);
|
||
}
|
||
|
||
animateToViewingAngle(angle, duration) {
|
||
this._runCommand('animateToViewingAngle', [angle, duration || 500]);
|
||
}
|
||
|
||
fitToElements(animated) {
|
||
this._runCommand('fitToElements', [animated]);
|
||
}
|
||
|
||
fitToSuppliedMarkers(markers, animated) {
|
||
this._runCommand('fitToSuppliedMarkers', [markers, animated]);
|
||
}
|
||
|
||
fitToCoordinates(coordinates = [], options = {}) {
|
||
const {
|
||
edgePadding = { top: 0, right: 0, bottom: 0, left: 0 },
|
||
animated = true,
|
||
} = options;
|
||
|
||
this._runCommand('fitToCoordinates', [coordinates, edgePadding, animated]);
|
||
}
|
||
|
||
setMapBoundaries(northEast, southWest) {
|
||
this._runCommand('setMapBoundaries', [northEast, southWest]);
|
||
}
|
||
|
||
/**
|
||
* Takes a snapshot of the map and saves it to a picture
|
||
* file or returns the image as a base64 encoded string.
|
||
*
|
||
* @param config Configuration options
|
||
* @param [config.width] Width of the rendered map-view (when omitted actual view width is used).
|
||
* @param [config.height] Height of the rendered map-view (when omitted actual height is used).
|
||
* @param [config.region] Region to render (Only supported on iOS).
|
||
* @param [config.format] Encoding format ('png', 'jpg') (default: 'png').
|
||
* @param [config.quality] Compression quality (only used for jpg) (default: 1.0).
|
||
* @param [config.result] Result format ('file', 'base64') (default: 'file').
|
||
*
|
||
* @return Promise Promise with either the file-uri or base64 encoded string
|
||
*/
|
||
takeSnapshot(args) {
|
||
// For the time being we support the legacy API on iOS.
|
||
// This will be removed in a future release and only the
|
||
// new Promise style API shall be supported.
|
||
if (Platform.OS === 'ios' && (arguments.length === 4)) {
|
||
console.warn('Old takeSnapshot API has been deprecated; will be removed in the near future'); //eslint-disable-line
|
||
const width = arguments[0]; // eslint-disable-line
|
||
const height = arguments[1]; // eslint-disable-line
|
||
const region = arguments[2]; // eslint-disable-line
|
||
const callback = arguments[3]; // eslint-disable-line
|
||
this._runCommand('takeSnapshot', [
|
||
width || 0,
|
||
height || 0,
|
||
region || {},
|
||
'png',
|
||
1,
|
||
'legacy',
|
||
callback,
|
||
]);
|
||
return undefined;
|
||
}
|
||
|
||
// Sanitize inputs
|
||
const config = {
|
||
width: args.width || 0,
|
||
height: args.height || 0,
|
||
region: args.region || {},
|
||
format: args.format || 'png',
|
||
quality: args.quality || 1.0,
|
||
result: args.result || 'file',
|
||
};
|
||
if ((config.format !== 'png') &&
|
||
(config.format !== 'jpg')) throw new Error('Invalid format specified');
|
||
if ((config.result !== 'file') &&
|
||
(config.result !== 'base64')) throw new Error('Invalid result specified');
|
||
|
||
// Call native function
|
||
if (Platform.OS === 'android') {
|
||
return NativeModules.AirMapModule.takeSnapshot(this._getHandle(), config);
|
||
} else if (Platform.OS === 'ios') {
|
||
return new Promise((resolve, reject) => {
|
||
this._runCommand('takeSnapshot', [
|
||
config.width,
|
||
config.height,
|
||
config.region,
|
||
config.format,
|
||
config.quality,
|
||
config.result,
|
||
(err, snapshot) => {
|
||
if (err) {
|
||
reject(err);
|
||
} else {
|
||
resolve(snapshot);
|
||
}
|
||
},
|
||
]);
|
||
});
|
||
}
|
||
return Promise.reject('takeSnapshot not supported on this platform');
|
||
}
|
||
|
||
_uiManagerCommand(name) {
|
||
return NativeModules.UIManager[getAirMapName(this.props.provider)].Commands[name];
|
||
}
|
||
|
||
_mapManagerCommand(name) {
|
||
return NativeModules[`${getAirMapName(this.props.provider)}Manager`][name];
|
||
}
|
||
|
||
_getHandle() {
|
||
return findNodeHandle(this.map);
|
||
}
|
||
|
||
_runCommand(name, args) {
|
||
switch (Platform.OS) {
|
||
case 'android':
|
||
NativeModules.UIManager.dispatchViewManagerCommand(
|
||
this._getHandle(),
|
||
this._uiManagerCommand(name),
|
||
args
|
||
);
|
||
break;
|
||
|
||
case 'ios':
|
||
this._mapManagerCommand(name)(this._getHandle(), ...args);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
render() {
|
||
let props;
|
||
|
||
if (this.state.isReady) {
|
||
props = {
|
||
region: null,
|
||
initialRegion: null,
|
||
onMarkerPress: this._onMarkerPress,
|
||
onChange: this._onChange,
|
||
onMapReady: this._onMapReady,
|
||
onLayout: this._onLayout,
|
||
...this.props,
|
||
};
|
||
if (Platform.OS === 'ios' && props.provider === ProviderConstants.PROVIDER_DEFAULT
|
||
&& GOOGLE_MAPS_ONLY_TYPES.includes(props.mapType)) {
|
||
props.mapType = MAP_TYPES.standard;
|
||
}
|
||
props.handlePanDrag = !!props.onPanDrag;
|
||
} else {
|
||
props = {
|
||
style: this.props.style,
|
||
region: null,
|
||
initialRegion: null,
|
||
onMarkerPress: this._onMarkerPress,
|
||
onChange: this._onChange,
|
||
onMapReady: this._onMapReady,
|
||
onLayout: this._onLayout,
|
||
};
|
||
}
|
||
|
||
if (Platform.OS === 'android' && this.props.liteMode) {
|
||
return (
|
||
<AIRMapLite
|
||
ref={ref => { this.map = ref; }}
|
||
{...props}
|
||
/>
|
||
);
|
||
}
|
||
|
||
const AIRMap = getAirMapComponent(this.props.provider);
|
||
|
||
return (
|
||
<AIRMap
|
||
ref={ref => { this.map = ref; }}
|
||
{...props}
|
||
/>
|
||
);
|
||
}
|
||
}
|
||
|
||
MapView.propTypes = propTypes;
|
||
MapView.viewConfig = viewConfig;
|
||
MapView.childContextTypes = childContextTypes;
|
||
|
||
MapView.MAP_TYPES = MAP_TYPES;
|
||
|
||
const nativeComponent = Component => requireNativeComponent(Component, MapView, {
|
||
nativeOnly: {
|
||
onChange: true,
|
||
onMapReady: true,
|
||
handlePanDrag: true,
|
||
},
|
||
});
|
||
const airMaps = {
|
||
default: nativeComponent('AIRMap'),
|
||
};
|
||
if (Platform.OS === 'android') {
|
||
airMaps.google = airMaps.default;
|
||
} else {
|
||
airMaps.google = googleMapIsInstalled ? nativeComponent('AIRGoogleMap') :
|
||
createNotSupportedComponent('react-native-maps: AirGoogleMaps dir must be added to your xCode project to support GoogleMaps on iOS.'); // eslint-disable-line max-len
|
||
}
|
||
const getAirMapComponent = provider => airMaps[provider || 'default'];
|
||
|
||
const AIRMapLite = NativeModules.UIManager.AIRMapLite &&
|
||
requireNativeComponent('AIRMapLite', MapView, {
|
||
nativeOnly: {
|
||
onChange: true,
|
||
onMapReady: true,
|
||
handlePanDrag: true,
|
||
},
|
||
});
|
||
|
||
MapView.Marker = MapMarker;
|
||
MapView.Polyline = MapPolyline;
|
||
MapView.Polygon = MapPolygon;
|
||
MapView.Circle = MapCircle;
|
||
MapView.UrlTile = MapUrlTile;
|
||
MapView.LocalTile = MapLocalTile;
|
||
MapView.Callout = MapCallout;
|
||
Object.assign(MapView, ProviderConstants);
|
||
MapView.ProviderPropType = PropTypes.oneOf(Object.values(ProviderConstants));
|
||
|
||
MapView.Animated = Animated.createAnimatedComponent(MapView);
|
||
MapView.AnimatedRegion = AnimatedRegion;
|
||
|
||
module.exports = MapView;
|