CircleMarker 的自定义形状(或更好的方法)

Custom shape of CircleMarker (or better approach)

我正在处理具有超过 2000 个标记坐标的数据集。

出于性能原因,我决定使用 preferCanvas 属性将这些标记添加到 canvas,它与 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>
  );
};

更新:

所以我决定创建一个自定义标记组件来扩展 react-leafletPath 组件,例如 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);

我认为最初我应该使用像 Canvas 这样的基本 Leaflet 渲染器,但我得到的是 Uncaught Error: The provided object is not a Layer.

还有其他人实现过类似的东西吗?

好的,所以在阅读 SO 答案后,我设法为 react-leaflet 实现了类似的东西。目前只是使用了leaflet的Canvas_updateCircle方法的代码,但对于不同的shape来说是一个开始

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

希望我的回答可以帮助到其他人。