23

I have seen this info: https://stackshare.io/stackups/leaflet-vs-mapbox-vs-openlayers

I'm developing at the same time a web application with react using OpenLayers. And I have to make the same app on mobile using react native but I don't know how to make it works.

Here is my code to web app using React + Openlayers:

import React, { Component } from 'react';
import './App.css';

// openlayers
import View from 'ol/view';
import Projection from 'ol/proj/projection';
import Map from 'ol/map';
import Zoom from 'ol/control/zoom';
import Tile from 'ol/layer/tile';
import OSM from 'ol/source/osm';

class App extends Component {

   constructor(props) {
     super(props);

     this.view = new View({
        center: [-41925.302985762304, 4789880.268977703],
        zoom: 12,
        minZoom: 2,
        maxZoom: 28,
           projection: new Projection({
             code: 'EPSG:3857',
             units: 'm'
           })
     });
   }

   componentDidMount() {
     this.map =  new Map({
     view: this.view,
     controls: [ new Zoom() ],
        layers: [new Tile({ source: new OSM() })],
        target: 'map'
     });
   }

   render() {
     console.log('-> render App')
     return (
       <div id="map" class="map"></div>
     );
   }
}

export default App;

And here is my problem, I don't know how to make it works in react native.

How can you add this.map ( javascript Map object ) inside WebView?

I have seen this example in other question React Native and WMS but I would like to work with React because I need to modify, add layers dynamically, etc.

import React, { Component } from 'react';
import { StyleSheet, View, WebView } from 'react-native';

// openlayers
import View from 'ol/view';
import Projection from 'ol/proj/projection';
import Map from 'ol/map';
import Zoom from 'ol/control/zoom';
import Tile from 'ol/layer/tile';
import OSM from 'ol/source/osm';

type Props = {};
export default class App extends Component<Props> {

constructor(props) {
   super(props);
   this.view = new View({
      center: [-41925.302985762304, 4789880.268977703],
      zoom: 12,
      minZoom: 2,
      maxZoom: 28,
      projection: new Projection({
         code: 'EPSG:3857',
         units: 'm'
      })
   });
}

componentDidMount() {
   this.map =  new Map({
     view: this.view,
     controls: [ new Zoom() ],
     layers: [new Tile({ name:'tile', source: new OSM() })],
     target: 'map'
   });
}

render() {
   var html = '<div id="map" class="map"></div>';
   return (
     <View style={styles.container}>
        <WebView 
           ref={webview => { this.webview = webview; }}
           source={{html}}
           onMessage={this.onMessage}/>
        />
     </View>
   );
  }
}

const styles = StyleSheet.create({
   container: {
     flex: 1,
     justifyContent: 'center',
     alignItems: 'center',
     backgroundColor: '#F5FCFF',
   }
});
1
  • I took some research, but nothing found about normal practice of react native and openlayers. Also openlayers is some kind of deprecated slippy maps software since leaflet comes to market. Maybe you can try take a look on github.com/reggie3/react-native-webview-leaflet Commented Jan 1, 2020 at 2:27

2 Answers 2

3

Well, I've been working with ReactJS and Leaflet and I'm quite satisfied. I can integrate leaflet pluggins with React easily, do my own pluggin, add styles, and so on. But if you need to add some kind of map rotation, leaflet will not work, you'll have to do it.

About the ReactNative issue: you can see this link, its a 'Webview based Leaflet Component for React Native'.

You can replace the WebView component by this component:

<WebViewLeaflet
  ref={(component) => (this.webViewLeaflet = component)}
  onLoad={this.onLoad}
  eventReceiver={this} // the component that will receive map events
/>

And add a function named onLoad to load the layers:

onLoad = (event) => {
  // log a message showing the map has been loaded
  console.log('onLoad received : ', event);

  //example of array of layers
  const mapLayers = [
    {
      name: 'streets',  // the name of the layer, this will be seen in the layer selection control
      checked: 'true',  // if the layer is selected in the layer selection control
      type: 'TileLayer',  // the type of layer as shown at https://react-leaflet.js.org/docs/en/components.html#raster-layers
      baseLayer: true,
      // url of tiles
      url: `https://api.tiles.mapbox.com/v4/mapbox.streets/{z}/{x}/{y}.png?access_token=${mapboxToken}`,
      // attribution string to be shown for this layer
      attribution:
        '&amp;copy <a href=&quot;http://osm.org/copyright&quot;>OpenStreetMap</a> contributors'
    }
  ]

  // set state
  this.setState(
    {
      ...this.state,
      mapState: { ...this.state.mapState, mapLoaded: true }
    },
    () => {
      // send an array of map layer information to the map
      this.webViewLeaflet.sendMessage({
        mapLayers
      });
    }
  );
}

If you need to add some Google map tiles or map data from Open Street Maps it will not work. If this is your case, you can try that link, (I never used it, is just a sugestion).

2
  • Could you add some specific info about how the links solve the problem/answer the question?
    – NatFar
    Commented Mar 2, 2020 at 22:32
  • I've added some examples about the first link. The second is just a sugestion, I dont know how this library work. Commented Mar 3, 2020 at 1:13
1

This is a bit outdated question, but since it has still active voting let's take a closer look. I would recommend you to use react-native-maps, since it's broadly supported with nice documentation. Other 3rd party libraries like react-native-webview-leaflet has a bit less flexibility.

2
  • can you use react-native-maps with OpenStreetMap?
    – showtime
    Commented Feb 24, 2023 at 7:55
  • Yes and no. You can use the OSM tiling. See github.com/react-native-maps/… for more info. But the maps API is either Google (you need an API key for that) or Apple (iOS only, no API key)
    – Mar Tijn
    Commented May 15, 2023 at 14:20

Not the answer you're looking for? Browse other questions tagged or ask your own question.