2

I am reposting a question that i asked in stackoverflow about leaflet and custom renderers.

Basically what i want to achieve is create a custom renderer that alters the shape of CircleMarker or extend the Path constructor to create custom shaped (vector) Markers.

What i've done so far is this:

import {
  CircleMarker as LeafletCircleMarker,
  Canvas as LeafletCanvas,
} from "leaflet";
import { withLeaflet, Path } from "react-leaflet";

const myRenderer = (layer) => LeafletCanvas({ padding: 0.5 });

class CustomMarker extends Path {
  createLeafletElement(props) {
    const enhancedProps = {
      ...props,
      renderer: myRenderer
    };

    const el = new LeafletCircleMarker(
      props.center,
      this.getOptions(enhancedProps)
    );
    this.contextValue = { ...props.leaflet, popupContainer: el };
    debugger;
    return el;
  }

  updateLeafletElement(fromProps, toProps) {
    if (toProps.center !== fromProps.center) {
      this.leafletElement.setLatLng(toProps.center);
    }

    if (toProps.radius !== fromProps.radius) {
      this.leafletElement.setRadius(toProps.radius);
    }
  }
}

export default withLeaflet(CustomMarker);

I am just setting the Canvas constructor as a renderer like the examples in the Leaflet docs but i am getting an Error: The provided object is not a Layer in layer/Layer.js:159 addLayer function.

Can someone please instruct me in how to implement a renderer?

2
  • Could you add a link to your SO question to keep things connected? Commented May 6, 2020 at 8:33
  • 1
    i will (add the link)...also i figure it out so i will add an answer. also if anyone has a better approach i would love to hear (read) it.
    – Zoti
    Commented May 6, 2020 at 8:40

1 Answer 1

1

ok so after reading this SO answer I managed to implement something similar for react-leaflet. Currently it just uses the code of leaflet's Canvas _updateCircle method, but it's a start for different shapes.

import {
  CircleMarker as LeafletCircleMarker,
  Canvas as LeafletCanvas,
} from "leaflet";
import { withLeaflet, Path } from "react-leaflet";

LeafletCanvas.include({
  _updateCustomMarker: function (layer) {
    if (!this._drawing || layer._empty()) {
      return;
    }

    var p = layer._point,
      ctx = this._ctx,
      r = Math.max(Math.round(layer._radius), 1),
      s = (Math.max(Math.round(layer._radiusY), 1) || r) / r;

    if (s !== 1) {
      ctx.save();
      ctx.scale(1, s);
    }

    ctx.beginPath();
    ctx.arc(p.x, p.y / s, r, 0, Math.PI * 2, false);

    if (s !== 1) {
      ctx.restore();
    }

    this._fillStroke(ctx, layer);
  },
});

class CustomMarker extends Path {
  createLeafletElement(props) {
    const MyMarker = LeafletCircleMarker.extend({
      _updatePath: function () {
        this._renderer._updateCustomMarker(this);
      },
    });

    const el = new MyMarker(props.center, this.getOptions(props));
    this.contextValue = { ...props.leaflet, popupContainer: el };

    return el;
  }

  updateLeafletElement(fromProps, toProps) {
    if (toProps.center !== fromProps.center) {
      this.leafletElement.setLatLng(toProps.center);
    }

    if (toProps.radius !== fromProps.radius) {
      this.leafletElement.setRadius(toProps.radius);
    }
  }
}

export default withLeaflet(CustomMarker);

I hope my answer can help someone else.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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