Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVGOverlay component #624

Closed
fenech opened this issue Oct 1, 2019 · 7 comments
Closed

SVGOverlay component #624

fenech opened this issue Oct 1, 2019 · 7 comments

Comments

@fenech
Copy link
Contributor

fenech commented Oct 1, 2019

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);
@PaulLeCam
Copy link
Owner

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?

@fenech
Copy link
Contributor Author

fenech commented Oct 15, 2019

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!

@fenech
Copy link
Contributor Author

fenech commented Oct 16, 2019

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!

@PaulLeCam
Copy link
Owner

Now available in v2.5.0 thanks to your PR!

@msaspence
Copy link

msaspence commented Jan 30, 2020

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.

@PaulLeCam
Copy link
Owner

Sorry I forgot to sync the website docs, it's been fixed now.

@MatiasManevi
Copy link

MatiasManevi commented Sep 29, 2020

Hi @fenech

I'm using this component and so far it is very useful!! But.. I'd really appreciate you look into this issues:

  1. SVGOverlay rotation #761
  2. The className attribute does not update its value on re-render when it depends on a prop.
    Meaning... it does not work when you want to change it dynamically. (I've already tested my code on a regular div and it worked, so there's something wrong with SVGOverlay component).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants