Reputation: 22769
Is there a way to use vector tiles from react-leaflet?
I am aware of Leaflet.VectorGrid, but it is not written for react-leaflet?
Upvotes: 7
Views: 6653
Reputation: 670
In case anyone finds this question and is wondering how to do this with MapLibre GL JS (FOSS fork of Mapbox GL JS) as the backend renderer, you can do this but it's not immediately obvious. The MapLibre equivalent plugin is actively maintained now while the Mapbox one is not.
Here is the component code (in TypeScript) for a MapLibre tile layer that you can use instead of TileLayer
in your React Leaflet MapContainer
:
import {
type LayerProps,
createElementObject,
createTileLayerComponent,
updateGridLayer,
withPane,
} from '@react-leaflet/core'
import L from 'leaflet'
import '@maplibre/maplibre-gl-leaflet'
export interface MapLibreTileLayerProps extends L.LeafletMaplibreGLOptions, LayerProps {
url: string,
attribution: string,
}
export const MapLibreTileLayer = createTileLayerComponent<
L.MaplibreGL,
MapLibreTileLayerProps
>(
function createTileLayer({ url, attribution, ...options }, context) {
const layer = L.maplibreGL({style: url, attribution: attribution, noWrap: true}, withPane(options, context))
return createElementObject(layer, context)
},
function updateTileLayer(layer, props, prevProps) {
updateGridLayer(layer, props, prevProps)
const { url, attribution } = props
if (url != null && url !== prevProps.url) {
layer.getMaplibreMap().setStyle(url)
}
if (attribution != null && attribution !== prevProps.attribution) {
layer.options.attribution = attribution
}
},
)
Full sample code lives in this repo on GitHub: https://github.com/stadiamaps/react-leaflet-demo
Upvotes: 0
Reputation: 9713
For react-leaflet v2
, export the MapBoxGLLayer
component wrapped with HOC withLeaflet()
to get it working.
Steps:
1.Install mapbox-gl-leaflet
.
npm i mapbox-gl-leaflet
2.Add mapbox-gl js and css to index.html
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.js'></script>
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.51.0/mapbox-gl.css' rel='stylesheet' />
3.Add this component.
import L from "leaflet";
import {} from "mapbox-gl-leaflet";
import PropTypes from "prop-types";
import { GridLayer, withLeaflet } from "react-leaflet";
class MapBoxGLLayer extends GridLayer {
createLeafletElement(props) {
return L.mapboxGL(props);
}
}
/*
* Props are the options supported by Mapbox Map object
* Find options here:https://www.mapbox.com/mapbox-gl-js/api/#new-mapboxgl-map-options-
*/
MapBoxGLLayer.propTypes = {
accessToken: PropTypes.string.isRequired,
style: PropTypes.string
};
MapBoxGLLayer.defaultProps = {
style: "mapbox://styles/mapbox/streets-v9"
};
export default withLeaflet(MapBoxGLLayer);
4.Use the MapBoxGLLayer
component.
class App extends Component {
state = {
center: [51.505, -0.091],
zoom: 13
};
render() {
return (
<div>
<Map center={this.state.center} zoom={this.state.zoom}>
<MapBoxGLLayer
accessToken={MAPBOX_ACCESS_TOKEN}
style="mapbox://styles/mapbox/streets-v9"
/>
</Map>
</div>
);
}
}
Find the working code here (Add your own mapbox token): https://codesandbox.io/s/ooypokn26y
Upvotes: 6
Reputation: 440
There are some really nice vector tiles examples in this react-leaflet issue (mapbox-gl example reproduced below).
// @flow
import L from 'leaflet'
import {} from 'mapbox-gl-leaflet'
import {PropTypes} from 'react'
import { GridLayer } from 'react-leaflet'
export default class MapBoxGLLayer extends GridLayer {
static propTypes = {
opacity: PropTypes.number,
accessToken: PropTypes.string.isRequired,
style: PropTypes.string,
zIndex: PropTypes.number,
}
createLeafletElement(props: Object): Object {
return L.mapboxGL(props)
}
}
and the usage of the above component:
<Map>
<MapBoxGLLayer
url={url}
accessToken={MAPBOX_ACCESS_TOKEN}
style='https://style.example.com/style.json'
/>
</Map>
NOTE: you may also need to npm install mapbox-gl
and import that library and assign into to the global window.mapboxgl = mapboxgl
to avoid issues with mapboxgl
being undefined.
Upvotes: 3
Reputation: 9408
You can create a custom component by extending the MapLayer component. You can see an example of how this is done in react-leaflet 1.0 in a project I contributed to here.
Upvotes: 2