OpenLayers (
https://openlayers.org/) is a "
high-performance, feature-packed (Javascript) library for all your mapping needs" for web sites. I spent some time figuring out how to use it with
ReactJS. As most of the available examples in the official documentation are for plain vanilla HTML/Javascript, I stumbled a few times trying to get it to work. This post summarises the steps to get a minimal OpenLayers - React component to work.
Installing OpenLayers for ReactJS
Assuming a
ReactJS project has been created e.g.
/path/to/React/project/, the first thing is to install the prerequisite software.
- Install OpenLayers package for node. Open a Terminal, change directory to the project root directory and type in the following command.
$ npm install ol --save
- Optional. Install Proj4Js and Material-UI.
$ npm install proj4 @material-ui/core --save
Create the React component for OpenLayers map
Under the
ReactJS project e.g.
/path/to/React/project/src/components/, create the
OpenLayers React component e.g.
OLMapFragment.js.
Code listing of OLMapFragment.js
import React from 'react'
import Grid from '@material-ui/core/Grid'
// Start Openlayers imports
import {
Map,
View
} from 'ol'
import {
GeoJSON,
XYZ
} from 'ol/format'
import {
Tile as TileLayer,
Vector as VectorLayer
} from 'ol/layer'
import {
Vector as VectorSource,
OSM as OSMSource,
XYZ as XYZSource,
TileWMS as TileWMSSource
} from 'ol/source'
import {
Select as SelectInteraction,
defaults as DefaultInteractions
} from 'ol/interaction'
import {
Attribution,
ScaleLine,
ZoomSlider,
Zoom,
Rotate,
MousePosition,
OverviewMap,
defaults as DefaultControls
} from 'ol/control'
import {
Style,
Fill as FillStyle,
RegularShape as RegularShapeStyle,
Stroke as StrokeStyle
} from 'ol/style'
import {
Projection,
get as getProjection
} from 'ol/proj'
// End Openlayers imports
class OLMapFragment extends React.Component {
constructor(props) {
super(props)
this.updateDimensions = this.updateDimensions.bind(this)
}
updateDimensions(){
const h = window.innerWidth >= 992 ? window.innerHeight : 400
this.setState({height: h})
}
componentWillMount(){
window.addEventListener('resize', this.updateDimensions)
this.updateDimensions()
}
componentDidMount(){
// Create an Openlayer Map instance with two tile layers
const map = new Map({
// Display the map in the div with the id of map
target: 'map',
layers: [
new TileLayer({
source: new XYZSource({
url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png',
projection: 'EPSG:3857'
})
}),
new TileLayer({
source: new TileWMSSource({
url: 'https://ahocevar.com/geoserver/wms',
params: {
layers: 'topp:states',
'TILED': true,
},
projection: 'EPSG:4326'
}),
name: 'USA'
}),
],
// Add in the following map controls
controls: DefaultControls().extend([
new ZoomSlider(),
new MousePosition(),
new ScaleLine(),
new OverviewMap()
]),
// Render the tile layers in a map view with a Mercator projection
view: new View({
projection: 'EPSG:3857',
center: [0, 0],
zoom: 2
})
})
}
componentWillUnmount(){
window.removeEventListener('resize', this.updateDimensions)
}
render(){
const style = {
width: '100%',
height:this.state.height,
backgroundColor: '#cccccc',
}
return (
<Grid container>
<Grid item xs={12}>
<div id='map' style={style} >
</div>
</Grid>
</Grid>
)
}
}
export default OLMapFragment
Use the React OpenLayers map component
Now in the
ReactJS project's
index.js file under
/path/to/React/project/src/, import in the newly created
OLMapFragment component and render it.
Listing of index.js
import React from 'react'
import { render} from 'react-dom'
import OLMapFragment from './js/components/OLMapFragment'
render(
<OLMapFragment />
,
document.getElementById('react-container')
)
Create the default index.html file
Finally, include links to
OpenLayer's style sheets in the project's
index.html file under
/path/to/React/project/src/.
Listing of index.html file
<!DOCTYPE html>
<html class="no-js" lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content='ie=edge'>
<title>Openlayers React</title>
<meta name="description" content="Explore planet Mars">
<meta name="viewport" content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" />
<!-- material-ui prerequisites -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<!-- end material-ui prerequisites -->
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css"
type="text/css" />
</head>
<body>
<!--[if lte IE 8]
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com">upgrade your browser</a></p>
<![endif]-->
<div id='react-container'></div>
</body>
</html>
Now, run the
ReactJS project with a web server and open the web page with an Internet browser.
The web map tiles are rendered in the React OpenLayers component.