Пользовательская форма CircleMarker (или лучший подход) - PullRequest
0 голосов
/ 04 мая 2020

Я работаю с набором данных с более чем 2000 координатами маркера.

По соображениям производительности я решил добавить эти маркеры на холст, используя опору preferCanvas, и она отлично работает с CircleMarker, который является единственным маркером в категории векторных слоев.

Но можно ли изменить форму CircleMarker?

Вот фрагмент кода:

const HeatMap = ({ markers }) => {
  return (
    <Map
      center={[50.3785, 14.9706]}
      zoom={1}
      preferCanvas={true}
      style={{ height: "400px", marginTop: "30px", marginBottom: "30px" }}
    >
      <TileLayer url={map_url} />
      { markers.map((i) => (
      <CircleMarker
        key={i.id}
        center={[i.lat, i.lon]}
        stroke={false}
        radius={4}
        fillOpacity={0.8}
      >
        <Tooltip>{i.details}</Tooltip>
      </CircleMarker>
    ))}
    </Map>
  );
};

UPDATE:

Итак, я решил создать Custom Компонент-маркер, расширяющий react-leaflet компонент Path, например CircleMarker:

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);

, и я подумал, что сначала я должен использовать базовый c Leaflet рендерер, например Canvas, но я получаю Uncaught Error: The provided object is not a Layer.

Кто-нибудь еще что-то подобное реализовал?

1 Ответ

0 голосов
/ 06 мая 2020

хорошо, поэтому после прочтения этого SO-ответа мне удалось реализовать нечто подобное для react-leaflet. В настоящее время он просто использует код метода листовки Canvas _updateCircle, но это начало для разных форм.

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);

Надеюсь, мой ответ может помочь кому-то другому.

...