diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index 0750b10..0000000 --- a/LICENSE.md +++ /dev/null @@ -1,55 +0,0 @@ -react-native-mapbox-gl copyright (c) 2015, Mapbox. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -=========================================================================== - -Mapbox GL uses portions of the Mapbox iOS SDK, which was derived from the -Route-Me open source project, including the Alpstein fork of it. - -The Route-Me license appears below. - -Copyright (c) 2008-2013, Route-Me Contributors -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. diff --git a/RCTMapboxGL/Settings.bundle/en.lproj/Root.strings b/RCTMapboxGL/Settings.bundle/en.lproj/Root.strings deleted file mode 100644 index 51959f6..0000000 Binary files a/RCTMapboxGL/Settings.bundle/en.lproj/Root.strings and /dev/null differ diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..e7d178b --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,37 @@ +buildscript { + repositories { + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:1.1.3' + } +} + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 23 + buildToolsVersion "23.0.1" + + defaultConfig { + minSdkVersion 16 + targetSdkVersion 22 + versionCode 1 + versionName "1.0" + } + lintOptions { + abortOnError false + } +} + +repositories { + mavenCentral() +} + +dependencies { + compile 'com.facebook.react:react-native:0.11.+' + compile('com.mapbox.mapboxsdk:mapbox-android-sdk:2.0.0@aar') { + transitive = true + } +} diff --git a/android/example.js b/android/example.js new file mode 100644 index 0000000..a428a46 --- /dev/null +++ b/android/example.js @@ -0,0 +1,89 @@ +'use strict'; + +var React = require('react-native'); +var Mapbox = require('react-native-mapbox-gl'); +var { + AppRegistry, + StyleSheet, + View +} = React; + +var MapExample = React.createClass({ + getInitialState() { + return { + center: { + latitude: 40.7223, + longitude: -73.9878 + }, + annotations: [{ + coordinates: [40.7223, -73.9878], + type: 'point', + title: 'Important!', + subtitle: 'Neat, this is a custom annotation image', + annotationImage: { + url: 'https://cldup.com/7NLZklp8zS.png', + height: 25, + width: 25 + }, + id: 'marker2' + }, { + coordinates: [40.7923, -73.9178], + type: 'point', + title: 'Important!', + subtitle: 'Neat, this is a custom annotation image', + annotationImage: { + url: 'https://cldup.com/7NLZklp8zS.png', + height: 25, + width: 25 + }, + id: 'marker2' + }, { + "coordinates": [[40.76572150042782,-73.99429321289062],[40.743485405490695, -74.00218963623047],[40.728266950429735,-74.00218963623047],[40.728266950429735,-73.99154663085938],[40.73633186448861,-73.98983001708984],[40.74465591168391,-73.98914337158203],[40.749337730454826,-73.9870834350586]], + "type": "polyline", + "strokeColor": "#00FB00", + "strokeWidth": 3, + "alpha": 0.5, + "id": "foobar" + }, { + "coordinates": [[40.749857912194386, -73.96820068359375], [40.741924698522055,-73.9735221862793], [40.735681504432264,-73.97523880004883], [40.7315190495212,-73.97438049316406], [40.729177554196376,-73.97180557250975], [40.72345355209305,-73.97438049316406], [40.719290332250544,-73.97455215454102], [40.71369559554873,-73.97729873657227], [40.71200407096382,-73.97850036621094], [40.71031250340588,-73.98691177368163], [40.71031250340588,-73.99154663085938]], + "type": "polygon", + "alpha":1, + "fillColor": "#FFFFFF", // http://developer.android.com/reference/android/graphics/Color.html#parseColor%28java.lang.String%29 + "strokeColor": "#FFFFFF", + "strokeWidth": 1, + "id": "zap" + }] + } + }, + render: function() { + return ( + + + + ); + } +}); + +var styles = StyleSheet.create({ + container: { + flex: 1 + }, + map: { + width: require('Dimensions').get('window').width, + flex: 1 + } +}); + +AppRegistry.registerComponent('your-app-name', () => MapExample); diff --git a/android/readme.md b/android/readme.md new file mode 100644 index 0000000..dcfa7a2 --- /dev/null +++ b/android/readme.md @@ -0,0 +1,59 @@ +#### Step 1 - NPM Install + +```shell +npm install --save react-native-mapbox-gl +``` +#### Step 2 - Update Gradle Settings + +```gradle +// file: android/settings.gradle +... + +include ':reactnativemapboxgl', ':app' +project(':reactnativemapboxgl').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-mapbox-gl/android') +``` + +#### Step 3 - Update app Gradle Build + +```gradle +// file: android/app/build.gradle +... + +dependencies { + ... + compile project(':reactnativemapboxgl') +} +``` + +#### Step 4 - Register React Package + +```java +... +import com.mapbox.reactnativemapboxgl.ReactNativeMapboxGLPackage; // <-- import + +public class MainActivity extends FragmentActivity implements DefaultHardwareBackBtnHandler { + + private ReactInstanceManager mReactInstanceManager; + private ReactRootView mReactRootView; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mReactRootView = new ReactRootView(this); + mReactInstanceManager = ReactInstanceManager.builder() + .setApplication(getApplication()) + .setBundleAssetName("index.android.bundle") + .setJSMainModuleName("index.android") + .addPackage(new MainReactPackage()) + .addPackage(new ReactNativeMapboxGLPackage()) // <-- Register package here + .setUseDeveloperSupport(BuildConfig.DEBUG) + .setInitialLifecycleState(LifecycleState.RESUMED) + .build(); + mReactRootView.startReactApplication(mReactInstanceManager, "AwesomeProject", null); + setContentView(mReactRootView); + } +... + +``` + +#### Step 5 - Add to project, [see example](/example.js) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml new file mode 100644 index 0000000..7959dbd --- /dev/null +++ b/android/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java new file mode 100644 index 0000000..e8037da --- /dev/null +++ b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLManager.java @@ -0,0 +1,158 @@ +package com.mapbox.reactnativemapboxgl; + + +import android.graphics.Color; +import android.util.Log; + +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.bridge.ReadableArray; +import com.facebook.react.uimanager.BaseViewPropertyApplicator; +import com.facebook.react.uimanager.CatalystStylesDiffMap; +import com.facebook.react.uimanager.SimpleViewManager; +import com.facebook.react.uimanager.ThemedReactContext; +import com.facebook.react.uimanager.UIProp; +import com.facebook.react.uimanager.ViewManager; +import com.mapbox.mapboxsdk.annotations.MarkerOptions; +import com.mapbox.mapboxsdk.annotations.PolygonOptions; +import com.mapbox.mapboxsdk.annotations.PolylineOptions; +import com.mapbox.mapboxsdk.views.MapView; +import com.mapbox.mapboxsdk.geometry.LatLng; +import com.facebook.react.bridge.ReactMethod; +import com.facebook.react.bridge.ReadableMap; +import android.graphics.Color; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Objects; +import java.util.List; + +public class ReactNativeMapboxGLManager extends SimpleViewManager { + public static final String REACT_CLASS = "RCTMapbox"; + + @UIProp(UIProp.Type.STRING) + public static final String PROP_ACCESS_TOKEN = "accessToken"; + @UIProp(UIProp.Type.ARRAY) + public static final String PROP_ANNOTATIONS = "annotations"; + @UIProp(UIProp.Type.MAP) + public static final String PROP_CENTER_COORDINATE = "centerCoordinate"; + @UIProp(UIProp.Type.BOOLEAN) + public static final String PROP_DEBUG_ACTIVE = "debugActive"; + @UIProp(UIProp.Type.NUMBER) + public static final String PROP_DIRECTION = "direction"; + @UIProp(UIProp.Type.BOOLEAN) + public static final String PROP_ROTATION_ENABLED = "rotationEnabled"; + @UIProp(UIProp.Type.STRING) + public static final String PROP_SCROLL_ENABLED = "scrollEnabled"; + @UIProp(UIProp.Type.STRING) + public static final String PROP_STYLE_URL = "styleUrl"; + @UIProp(UIProp.Type.BOOLEAN) + public static final String PROP_ZOOM_ENABLED = "zoomEnabled"; + @UIProp(UIProp.Type.NUMBER) + public static final String PROP_ZOOM_LEVEL = "zoomLevel"; + + @Override + public String getName() { + return REACT_CLASS; + } + + @Override + public MapView createViewInstance(ThemedReactContext context) { + MapView mv = new MapView(context); + mv.setAccessToken("pk.eyJ1IjoiYm9iYnlzdWQiLCJhIjoiTi16MElIUSJ9.Clrqck--7WmHeqqvtFdYig"); + mv.setStyleUrl("asset://styles/dark-v8.json"); + mv.onCreate(null); + mv.onStart(); + return mv; + } + + @Override + public void updateView(final MapView view, + final CatalystStylesDiffMap props) { + + BaseViewPropertyApplicator.applyCommonViewProperties(view, props); + if (props.hasKey(PROP_ACCESS_TOKEN)) { + view.setAccessToken(props.getString(PROP_ACCESS_TOKEN)); + } + if (props.hasKey(PROP_ANNOTATIONS)) { + int size = props.getArray(PROP_ANNOTATIONS).size(); + for (int i = 0; i < size; i++) { + ReadableMap annotation = props.getArray(PROP_ANNOTATIONS).getMap(i); + String type = annotation.getString("type"); + if (type.equals("point")) { + double latitude = annotation.getArray("coordinates").getDouble(0); + double longitude = annotation.getArray("coordinates").getDouble(1); + String title = annotation.getString("title"); + String subtitle = annotation.getString("title"); + LatLng markerCenter = new LatLng(latitude, longitude); + MarkerOptions marker = new MarkerOptions(); + marker.position(markerCenter); + marker.title(title); + marker.snippet(subtitle); + marker.isDraggable(); + view.addMarker(marker); + } else if (type.equals("polyline")) { + int coordSize = annotation.getArray("coordinates").size(); + PolylineOptions polyline = new PolylineOptions(); + for (int p = 0; p < coordSize; p++) { + double latitude = annotation.getArray("coordinates").getArray(p).getDouble(0); + double longitude = annotation.getArray("coordinates").getArray(p).getDouble(1); + polyline.add(new LatLng(latitude, longitude)); + } + double strokeAlpha = annotation.getDouble("alpha"); + int strokeColor = Color.parseColor(annotation.getString("strokeColor")); + float strokeWidth = annotation.getInt("strokeWidth"); + polyline.alpha((float) strokeAlpha); + polyline.color(strokeColor); + polyline.width(strokeWidth); + view.addPolyline(polyline); + } else if (type.equals("polygon")) { + int coordSize = annotation.getArray("coordinates").size(); + PolygonOptions polygon = new PolygonOptions(); + for (int p = 0; p < coordSize; p++) { + double latitude = annotation.getArray("coordinates").getArray(p).getDouble(0); + double longitude = annotation.getArray("coordinates").getArray(p).getDouble(1); + polygon.add(new LatLng(latitude, longitude)); + } + double fillAlpha = annotation.getDouble("alpha"); + int fillColor = Color.parseColor(annotation.getString("fillColor")); + int strokeColor = Color.parseColor(annotation.getString("strokeColor")); + float strokeWidth = annotation.getInt("strokeWidth"); + polygon.alpha((float) fillAlpha); + polygon.fillColor(fillColor); + polygon.strokeColor(strokeColor); + polygon.strokeWidth(strokeWidth); + view.addPolygon(polygon); + } + } + } + if (props.hasKey(PROP_DEBUG_ACTIVE)) { + view.setDebugActive(props.getBoolean(PROP_DEBUG_ACTIVE, false)); + } + if (props.hasKey(PROP_DIRECTION)) { + view.setDirection(props.getFloat(PROP_DIRECTION, 0)); + } + if (props.hasKey(PROP_CENTER_COORDINATE)) { + ReadableMap center = props.getMap(PROP_CENTER_COORDINATE); + double latitude = center.getDouble("latitude"); + double longitude = center.getDouble("longitude"); + view.setCenterCoordinate(new LatLng(latitude, longitude)); + } + if (props.hasKey(PROP_ROTATION_ENABLED)) { + view.setRotateEnabled(props.getBoolean(PROP_ROTATION_ENABLED, true)); + } + if (props.hasKey(PROP_SCROLL_ENABLED)) { + view.setScrollEnabled(props.getBoolean(PROP_SCROLL_ENABLED, true)); + } + if (props.hasKey(PROP_STYLE_URL)) { + view.setStyleUrl(props.getString(PROP_STYLE_URL)); + } + if (props.hasKey(PROP_STYLE_URL)) { + view.setZoomEnabled(props.getBoolean(PROP_ZOOM_ENABLED, true)); + } + if (props.hasKey(PROP_ZOOM_LEVEL)) { + view.setZoomLevel(props.getFloat(PROP_ZOOM_LEVEL, 0)); + } + + super.updateView(view, props); + } +} diff --git a/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLPackage.java b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLPackage.java new file mode 100644 index 0000000..389c60e --- /dev/null +++ b/android/src/main/java/com/mapbox/reactnativemapboxgl/ReactNativeMapboxGLPackage.java @@ -0,0 +1,32 @@ +package com.mapbox.reactnativemapboxgl; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.JavaScriptModule; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import android.util.Log; + +public class ReactNativeMapboxGLPackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } + + @Override + public List> createJSModules() { + return Collections.emptyList(); + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Arrays.asList( + new ReactNativeMapboxGLManager() + ); + } +} diff --git a/index.android.js b/index.android.js new file mode 100644 index 0000000..8582980 --- /dev/null +++ b/index.android.js @@ -0,0 +1,52 @@ +var React = require('react-native'); +var { NativeModules, requireNativeComponent } = React; + + +var MapView = React.createClass({ + name: 'RCTMapbox', + propTypes: { + accessToken: React.PropTypes.string, + annotations: React.PropTypes.arrayOf(React.PropTypes.shape({ + title: React.PropTypes.string, + subtitle: React.PropTypes.string, + coordinates: React.PropTypes.arrayOf(), + alpha: React.PropTypes.number, + fillColor: React.PropTypes.string, + strokeColor: React.PropTypes.string, + strokeWidth: React.PropTypes.number + })), + centerCoordinate: React.PropTypes.shape({ + latitude: React.PropTypes.number.isRequired, + longitude: React.PropTypes.number.isRequired + }), + debugActive: React.PropTypes.bool, + direction: React.PropTypes.number, + rotationEnabled: React.PropTypes.bool, + scrollEnabled: React.PropTypes.bool, + styleUrl: React.PropTypes.string, + zoomEnabled: React.PropTypes.bool, + zoomLevel: React.PropTypes.number + }, + getDefaultProps() { + return { + centerCoordinate: { + latitude: 0, + longitude: 0 + }, + debugActive: false, + direction: 0, + rotationEnabled: true, + scrollEnabled: true, + styleUrl: 'asset://styles/streets-v8.json', + zoomEnabled: true + }; + }, + render: function() { + return (); + } +}); + + +module.exports = requireNativeComponent('RCTMapbox', MapView); diff --git a/RCTMapboxGL.ios.js b/index.ios.js similarity index 99% rename from RCTMapboxGL.ios.js rename to index.ios.js index 0738fd5..29d30cc 100644 --- a/RCTMapboxGL.ios.js +++ b/index.ios.js @@ -95,7 +95,6 @@ var MapView = React.createClass({ zoomEnabled: true }; }, - render: function() { return (=0.4.3" }, @@ -26,7 +26,7 @@ }, "scripts": { "preinstall": "./scripts/download-mapbox-gl-native-ios.sh 2.1.2", - "test": "eslint example.js RCTMapboxGL.ios.js", + "test": "eslint example.js index.ios.js index.android.js", "start": "node_modules/react-native/packager/packager.sh" }, "devDependencies": { diff --git a/readme.md b/readme.md index b16ff9f..0908a1e 100644 --- a/readme.md +++ b/readme.md @@ -2,14 +2,21 @@ _A React Native component for building maps with [Mapbox GL](https://www.mapbox.com/mapbox-gl/)_ + ``` npm install react-native-mapbox-gl --save ``` ![](https://cldup.com/A8S_7rLg1L.png) -# [Installation](/install.md) +# Installation +* [iOS](/ios/install.md) +* [Android](/ios/install.md) -# [API](/API.md) +# API +* [iOS](/ios/API.md) +* [Android](/ios/API.md) -# [Example](/example.js) +# Example +* [iOS](/ios//example.js) +* [Android](/ios//example.js) diff --git a/scripts/download-mapbox-gl-native-ios.sh b/scripts/download-mapbox-gl-native-ios.sh index ed0b083..9a774af 100755 --- a/scripts/download-mapbox-gl-native-ios.sh +++ b/scripts/download-mapbox-gl-native-ios.sh @@ -3,6 +3,7 @@ VERSION=$1 echo "Downloading Mapbox GL iOS $VERSION, this may take a minute." +cd ios/ if ! which curl > /dev/null; then echo "curl command not found. Please install curl"; exit 1; fi; if ! which unzip > /dev/null; then echo "unzip command not found. Please install unzip"; exit 1; fi;