Hi, I notice that this library doesn't contain a component for Leaflet's SVGOverlay. I made one for my own project - it's written in TypeScript but it would be fairly easy to port to JS/Flow and open a PR if you're interested.
To begin with, I tried to inherit from MapLayer, but I decided in the end that I preferred to render the svg container in the component, and inherit from MapComponent instead.
Happy to open a PR if you like, but as a starting point I'll leave the TS code here.
import { LatLngBounds, SVGOverlay as LeafletSVGOverlay } from "leaflet";
import React from "react";
import {
LayerContainer,
LeafletContext,
LeafletProvider,
MapComponent,
MapLayerProps,
withLeaflet
} from "react-leaflet";
type Props = {
attribution?: string;
bounds: LatLngBounds;
opacity?: number;
zIndex?: number;
} & MapLayerProps;
class SVGOverlay extends MapComponent<Props, LeafletSVGOverlay> {
leafletElement: LeafletSVGOverlay;
private container: SVGSVGElement;
private contextValue: LeafletContext;
constructor(props: Props) {
super(props);
this.bindContainer = this.bindContainer.bind(this);
}
get layerContainer(): LayerContainer {
return this.props.leaflet.layerContainer;
}
createLeafletElement(props: Props) {
return new LeafletSVGOverlay(this.container, props.bounds, this.getOptions(props));
}
updateLeafletElement(fromProps: Props, toProps: Props) {
if (toProps.bounds !== fromProps.bounds) {
this.leafletElement.setBounds(toProps.bounds);
}
if (toProps.opacity !== fromProps.opacity) {
this.leafletElement.setOpacity(toProps.opacity);
}
if (toProps.zIndex !== fromProps.zIndex) {
this.leafletElement.setZIndex(toProps.zIndex);
}
}
componentDidMount() {
this.leafletElement = this.createLeafletElement(this.props);
this.layerContainer.addLayer(this.leafletElement, "");
this.contextValue = { ...this.props.leaflet, popupContainer: this.leafletElement };
super.componentDidMount();
}
componentDidUpdate(prevProps: Props, prevState: {}) {
super.componentDidUpdate(prevProps, prevState);
this.updateLeafletElement(prevProps, this.props);
}
componentWillUnmount() {
super.componentWillUnmount();
this.layerContainer.removeLayer(this.leafletElement);
}
render() {
const { children } = this.props;
return (
<svg ref={this.bindContainer}>
{this.contextValue == null ? (
<>{children}</>
) : (
<LeafletProvider value={this.contextValue}>{children}</LeafletProvider>
)}
</svg>
);
}
private bindContainer(ref: SVGSVGElement) {
this.container = ref;
}
}
export default withLeaflet<Props>(SVGOverlay);
Hi, yes opening a PR for it would be nice, thanks!
If you open a PR, could you please include an example and the documentation for the added component?
I'm actually running into an issue with the component now: if it is unmounted before the map, I get a DOMException: "Node was not found". If I manage to fix the problem I'll open a PR!
I realised what I was doing wrong: rendering the svg with React and then passing it to Leaflet meant that both libraries were trying to take control of the same element. I just opened a pull request!
Now available in v2.5.0 thanks to your PR!
~This is still missing from the docs~, looks like it has docs but https://react-leaflet.js.org needs updating if I hadn't found this I would have ended up reimplementing it myself.
Sorry I forgot to sync the website docs, it's been fixed now.
Hi @fenech
I'm using this component and so far it is very useful!! But.. I'd really appreciate you look into this issues:
className attribute does not update its value on re-render when it depends on a prop.div and it worked, so there's something wrong with SVGOverlay component).