- Documentation(ko)
- Tutorial(ko) 1 - Installation, Register Console API
- Tutorial(ko) 2 - Camrae, Position of Map
Note
The code comments and Documentation are unfortunately all written in Korean. However, you can use a translator or infer the meaning of the props' names and default values to easily understand and use them, even without knowing Korean.
Always remember that you can refer to the Naver Map SDK's English Official Documentation to get a general idea of how to use it.
Support Table
React Native Naver Map | React Native | Note |
---|---|---|
≥2.1.0 |
≥ 0.74 |
Drop Bridge Support & 0.74 required |
≥2.x |
New Architecture Only | Drop Old Architecture Support, You should turn off bridgeless if want to render http web image marker |
<2.x |
Old Architecture + New Architecture |
Important
The 1.x
version supports the Old Architecture (Bridge), but starting from the 2.x
version, support for it will be discontinued. If your project has not transitioned to the New Architecture, please use the 1.x
version.
We have structured the API Docs which describe almost all types.
We have maximized readability and you can check the usage of the desired component types, Prop
, and Ref
on the component
side.
Using the expo config plugin, you can easily build in the Expo environment regardless of the architecture.
While it cannot be used in Expo Go or Snack, it can easily be used in the development build and production environments.
Important
[iOS, Android] x [new arch, old arch] x [debug, release]
We have tested that it renders correctly under all 8 conditions.
- Basic symbols provided by Naver Map (
symbol
) - Local image resources of the React Native project
- Local image resources of the native project optimized for performance - Android (Drawable), iOS (Bundle Asset)
- HTTP network web images
- React Native Custom View passed as
children
We support the latest version of the SDK, and you can manipulate the latest features of Naver Map using Props and Commands.
# npm
npm install --save @mj-studio/react-native-naver-map
# yarn
yarn add @mj-studio/react-native-naver-map
# expo
npx expo install @mj-studio/react-native-naver-map
For iOS, you should install pods
For more detailed settings, please refer to the Official Documentation.
Import Naver SDK Maven Repository to android/build.gradle
.
allprojects {
repositories {
maven {
url "https://repository.map.naver.com/archive/maven"
}
}
}
<manifest>
<application>
<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
android:value="YOUR_CLIENT_ID_HERE" />
</application>
</manifest>
Currently, this package will request location permission for showing user's current location.
<manifest>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
# optional for background location
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>
Detailed information related to permissions is listed below.
For more detailed settings, please refer to the Official Documentation.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NMFClientId</key>
<string>YOUR_CLIENT_ID_HERE</string>
<dict>
<plist>
Currently, this package will request location permission for showing user's current location.
<plist version="1.0">
<dict>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>{{usage description}}</string>
<key>NSLocationTemporaryUsageDescriptionDictionary</key>
<dict>
<key>{{your purpose key}}</key>
<string>{{usage description}}</string>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string>{{usage description}}</string>
</dict>
</plist>
Detailed information related to permissions is listed below.
This is for inject naver maven repository.
npx expo install expo-build-properties
{
...
"plugins": [
[
"@mj-studio/react-native-naver-map",
{
"client_id": "{{Naver Map Client Key}}",
// (optional, you can set with expo-location instead of this package)
"android": {
"ACCESS_FINE_LOCATION": true,
"ACCESS_COARSE_LOCATION": true,
"ACCESS_BACKGROUND_LOCATION": true
},
// (optional, you can set with expo-location instead of this package)
"ios": {
"NSLocationAlwaysAndWhenInUseUsageDescription": "{{ your location usage description }}",
"NSLocationWhenInUseUsageDescription": "{{ your location usage description }}",
"NSLocationTemporaryUsageDescriptionDictionary": {
"purposeKey": "{{ your purpose key }}",
"usageDescription": "{{ your location usage description }}"
}
}
}
],
[
"expo-build-properties",
{
"android": {
"extraMavenRepos": ["https://repository.map.naver.com/archive/maven"]
}
}
],
...
]
}
Expo does not require the setup methods for Android and iOS described above.
Detailed information related to permissions is listed below.
const jejuRegion: Region = {
latitude: 33.20530773,
longitude: 126.14656715029,
latitudeDelta: 0.38,
longitudeDelta: 0.8,
};
...
<NaverMapView
ref={ref}
style={{ flex: 1 }}
mapType={mapType}
layerGroups={{
BUILDING: true,
BICYCLE: false,
CADASTRAL: false,
MOUNTAIN: false,
TRAFFIC: false,
TRANSIT: false,
}}
initialRegion={jejuRegion}
isIndoorEnabled={indoor}
symbolScale={symbolScale}
lightness={lightness}
isNightModeEnabled={nightMode}
isShowCompass={compass}
isShowIndoorLevelPicker={indoorLevelPicker}
isShowScaleBar={scaleBar}
isShowZoomControls={zoomControls}
isShowLocationButton={myLocation}
isExtentBoundedInKorea
logoAlign={'TopRight'}
locale={'ja'}
onInitialized={() => console.log('initialized!')}
onOptionChanged={() => console.log('Option Changed!')}
onCameraChanged={(args) => console.log(`Camera Changed: ${formatJson(args)}`)}
onTapMap={(args) => console.log(`Map Tapped: ${formatJson(args)}`)}
>
<NaverMapMarkerOverlay
latitude={33.3565607356}
longitude={126.48599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
/>
{/* Not Working in iOS Old Architecture Yet */}
<NaverMapMarkerOverlay*
latitude={33.4165607356}
longitude={126.48599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
>
<View style={{ width: 100, height: 100, backgroundColor: 'red' }} />
</NaverMapMarkerOverlay>
<NaverMapMarkerOverlay
latitude={33.2565607356}
longitude={127.8599018}
onTap={() => console.log(1)}
anchor={{ x: 0.5, y: 1 }}
caption={{
key: '1',
text: 'hello',
}}
subCaption={{
key: '1234',
text: '123',
}}
width={100}
height={100}
image={{ uri: 'https://picsum.photos/100/100' }}
/>
<NaverMapCircleOverlay
latitude={33.17827398}
longitude={126.349895729}
radius={50000}
color={'#f2f1'}
outlineColor={'#aaa'}
outlineWidth={2}
onTap={() => console.log('hi')}
/>
<NaverMapPolygonOverlay
outlineWidth={5}
outlineColor={'#f2f2'}
color={'#0068'}
coords={[
{ latitude: 33.2249594, longitude: 126.54180047 },
{ latitude: 33.25683311547, longitude: 126.18193 },
{ latitude: 33.3332807, longitude: 126.838389399 },
]}
/>
<NaverMapPathOverlay
coords={[
{ latitude: 33.5249594, longitude: 126.24180047 },
{ latitude: 33.25683311547, longitude: 126.18193 },
{ latitude: 33.3332807, longitude: 126.838389399 },
]}
width={8}
color={'red'}
progress={-0.6}
passedColor={'green'}
/>
</NaverMapView>
All codes have JSDoc comments inserted, so you can start developing without Documentation.
However, if you want to check exactly what types exist and what properties they mean, please refer to the Documentation.
Permissions should be managed directly within the app by default.
We will look at an example of using the react-native-permissions library to manage this.
Tip
If you are an Expo user, you can indicate that you will be using permissions by referring to expo-location. Therefore, most of the content below is not necessary, and after examining what permissions are needed and how to specify them, you should follow the usage at expo-location.
First, install and set up the package:
yarn add react-native-permissions
Please refer to the Usage directly for the platform-specific setup method for react-native-permission
and properly modify Podfile(iOS)
, AndroidManifest.xml(Android)
.
iOS is involved with three types of permissions:
NSLocationAlwaysAndWhenInUseUsageDescription(>= iOS 11)
- Allows the app to access location information both in the foreground and the background.
- From iOS 11, this key should be used instead of NSLocationAlwaysUsageDescription.
NSLocationWhenInUseUsageDescription
- Allows the app to access location information when it is in the foreground (i.e., when the user is actively using the app).
NSLocationTemporaryUsageDescriptionDictionary(>= iOS 14)
- Allows the app temporarily access to precise location data. This is used when the app only needs precise location for certain tasks.
Tip
If your app does not support devices below iOS 11, you do not need to list NSLocationAlwaysUsageDescription
.
If it does support, then you should set it as well.
Then, in the Podfile
, you allow the following three permissions:
setup_permissions([
'LocationAccuracy',
'LocationAlways',
'LocationWhenInUse',
...
])
Activate the Background Modes
tab in the app target in Xcode and select the Location updates
option.
This is necessary for receiving location in the background, so it does not need to be set if it is not required.
The FusedLocationSource
used internally by the Naver Map SDK automatically makes a permission request the moment the user sets the isShowLocationButton prop to true
.
Android can implement permissions relatively simply.
Just specify the following permissions in AndroidManifest.xml
:
android.permission.ACCESS_FINE_LOCATION
- Permission for precise location information
android.permission.ACCESS_COARSE_LOCATION
- Permission for approximate location information
android.permission.ACCESS_BACKGROUND_LOCATION
- Permission for location information in the background
If you have completed the configuration up to this point, you can request permissions in screens that require a map as follows:
For Bare RN Project or ejected Expo (react-native-permissions
)
// useEffect is simply used to be called when the component mounts..
useEffect(() => {
if (Platform.OS === 'ios') {
request(PERMISSIONS.IOS.LOCATION_ALWAYS).then((status) => {
console.log(`Location request status: ${status}`);
if (status === 'granted') {
requestLocationAccuracy({
purposeKey: 'common-purpose', // replace your purposeKey of Info.plist
})
.then((accuracy) => {
console.log(`Location accuracy is: ${accuracy}`);
})
.catch((e) => {
console.error(`Location accuracy request has been failed: ${e}`);
});
}
});
}
if (Platform.OS === 'android') {
requestMultiple([
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
PERMISSIONS.ANDROID.ACCESS_BACKGROUND_LOCATION,
])
.then((status) => {
console.log(`Location request status: ${status}`);
})
.catch((e) => {
console.error(`Location request has been failed: ${e}`);
});
}
}, []);
For Expo (expo-location
)
import * as Location from 'expo-location'
...
useEffect(() => {
(async () => {
try {
const {granted} = await Location.requestForegroundPermissionsAsync();
/**
* Note: Foreground permissions should be granted before asking for the background permissions
* (your app can't obtain background permission without foreground permission).
*/
if(granted) {
await Location.requestBackgroundPermissionsAsync();
}
} catch(e) {
console.error(`Location request has been failed: ${e}`);
}
})();
}, []);
Note
Descriptions for most types and props are also written in the code comments, and this project supports TypeScript, so checking only in the code will suffice for use.
- ✅ Fully Supported
⚠️ Developing, lack of features yet- 📦 Planned
Component | iOS | Android | Description |
---|---|---|---|
NaverMapView | ✅ | ✅ | Map |
NaverMapMarkerOverlay | ✅ | ✅ | Marker Overlay |
Info Window | 📦 | 📦 | Callout Overlay, Tooltip |
NaverMapCircleOverlay | ✅ | ✅ | Circle Overlay |
NaverMapPolylineOverlay | ✅ | ✅ | Polyline Overlay |
NaverMapPolygonOverlay | ✅ | ✅ | Polygon |
NaverMapLocationOverlay | 📦 | 📦 | Custom Location Overlay |
NaverMapGroundOverlay | ✅ | ✅ | Ground Overlay |
NaverMapPathOverlay | ✅ | ✅ | Path Overlay |
NaverMapMultipartPathOverlay | 📦 | 📦 | Multipath Overlay |
NaverMapArrowPathOverlay | ✅ | ✅ | Arrow Path Overlay |
There are a total of 5 types of markers.
Important
[iOS, Android] x [new arch, old arch] x [debug, release]
Tested to render correctly under all 8 conditions.
Tip
reuseIdentifier
is automatically cached even if not provided.
Ideally, all markers should use the width
, height
prop. Currently, for type 2, the size appears differently in debug/release builds without width
, height
.
It appears correctly in release.
- Naver Map Basic Symbol (green, red, gray, ...) (caching ✅)
image={{symbol: 'green'}}
- Local Resource (
require
react native image file) (caching ✅)
image={require('./marker.png')}
- Local Native Resource
image={{assetName: 'asset_image'}}
- iOS: image asset name in the main bundle
- Android: name in the resources' drawable
- Network Image (caching ✅)
image={{httpUri: 'https://example.com/image.png'}}
Warning
Attributes like header are currently not supported.
- Custom React View (caching ❌)
On iOS(new arch), collapsable=false
must be set for Views to function.
Tip
To change the appearance of a marker, dependencies must be passed as the key
of the topmost child.
<NaverMapMarkerOverlay width={width} height={height} ...>
<View key={`${text}/${width}/${height}`} collapsable={false} style={{width, height}}>
<Text>{text}</Text>
</View>
</NaverMapMarkerOverlay>
Important
This type can significantly impact performance when created in large quantities. It is recommended to use images whenever possible or keep usage simple.
Currently, this type tracks the position of children by slightly customizing React Native’s Shadow Node on Android and inserting the actual Android View
.
On iOS, simply draw UIView
to canvas as UIImage
.
Both methods do not yet support image caching (possible in the future with attributes like reuseableIdentifier
), and each marker consumes a significant amount of resources.
- ✅ Done
- 📦 Planned
- ❓ Maybe Planned
- ❌ Not Planned
Prop | iOS | Android |
---|---|---|
isLogoInteractionEnabled | ❌ | ❌ |
gestureFrictions | 📦 | 📦 |
Event | iOS | Android |
---|---|---|
onTapSymbol | 📦 | 📦 |
onAuthFailed | ❌ | ❌ |
onLocationChange | 📦 | 📦 |
iOS | Android | |
---|---|---|
onLongTap | ❌ | 📦 |
Prop | iOS | Android |
---|---|---|
caption-fontFamily | ❓ | ❓ |
subcaption-fontFamily | ❓ | ❓ |
iOS | Android | |
---|---|---|
Bridge | ✅ | ✅ |
Fabric | ✅️ | ✅️ |
- Project Started (23.04.01)
- Project Setup & Component Structure (23.04.03)
- General Props & Commands (23.04.05)
- Camera, Region, Commands, Events (23.04.07)
- Implement Basic Overlays (23.04.10)
- Location Service (23.04.10)
- Support Paper(Old Arch) (23.04.11)
- Release (23.04.11)
- Support Expo with config plugin (23.04.12)
- Docs
- Implement Clustering (23.04.24)
- Implement ArrowheadPath Overlay (23.05.01)
- Implement Ground Overlay (23.05.01)
- Implement Location Overlay Commands <- 🔥
- Implement MutlPath Overlay <- 🔥
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT