React Leaflet V3 自定义控件

Dyl*_*mek 6 react-leaflet

有一个新的 react-leaflet 版本,可以在这里找到:npm install react-leaflet/next docs:https ://react-leaflet-v3.now.sh/docs/start-introduction

这是使用钩子的完全重写。

基于这些新的钩子,我正在尝试编写一个自定义图层控件,我主要只是想将其分成多个组并从 material-ui 渲染我的反应组件,以使地图样式与我的应用程序的其余部分保持一致。根据我的理解,钩子的使用方式如下:

基本控制示例

const MyControl = Control.extend({
  onAdd: map => {
    let container = DomUtil.create('div');
    container.innerHTML += 'My Control';

    return container;
  },
  // this one is optional
  onRemove: map => {},
});

const useControlElement = createElementHook(
  function createControl(_ref, ctx) {
    const context = useLeafletContext();
    var instance = new MyControl(position);
    return {
      instance: instance,
      context: Object.assign({}, ctx, {
        control: instance,
      }),
    };
  },
  function updateControl(control, props, prevProps) {},
);

const useControl = createControlHook(useControlElement);

const FinalControl = createContainerComponent(useControl);

function ControlComponent({ children }) {
  const controlRef = useRef();
  // if ref exits portal children through, note: using react scripts to support ?
   if(ref.?current?.getContainer()){
     ReactDOM.createPortal(children, ref.current.getContainer())
   }
  return <FinalControl ref={controlRef} />;
}

export default ControlComponent;
Run Code Online (Sandbox Code Playgroud)

但是,子项永远不会呈现,因为控件仅添加到 componentDidMount 上。

我想在 React/JSX/JS 中编写这个层控件我不想完全使用 html 来构建它,即 L.Control,并使用传单 domutil 因为这无论如何都不会与我的反应样式一起使用并提供受限访问到我的 redux 商店。所以我试图通过一个基本的控件来传送我的组件,比如 react-leaflet-control 是如何工作的

我是否以正确的方式接近这个?我只是在自动取款机上转来转去,试图让它以一种好的方式工作。我几乎要渲染一个反应组件作为地图的子级并将位置设置为绝对(我知道这是错误的方式,但确实有效)

IE

<MapContainer>
  <ReactComponent />
</MapContiner>

Run Code Online (Sandbox Code Playgroud)

该文档有一个自定义组件的示例,但这仅适用于已经存在的传单组件,即“核心架构”部分中的方形示例。任何帮助表示赞赏!

小智 6

这可以使用 createControlComponent 钩子进一步简化

import { createControlComponent } from "@react-leaflet/core";
import { Control, DomUtil } from "leaflet";

Control.Watermark = Control.extend({
  onAdd: function (map) {
    const img = DomUtil.create("img");
    img.src = "./logo.png";
    img.style.width = "200px";
    return img;
  },

  onRemove: function (map) {},
});

export const WatermarkControl = createControlComponent(
  (props) => new Control.Watermark(props)
);
Run Code Online (Sandbox Code Playgroud)


小智 4

感谢扎克的回答,我可以用这种方式做到这一点。

依赖版本:

"react-leaflet": "^3.0.5",
"leaflet": "^1.7.1",
Run Code Online (Sandbox Code Playgroud)

这是一个扩展 Leaflet 控件的组件。您可以使用选项来自定义带有接收到的道具的组件。

//MyComponent.jsx
import React from 'react';
import {useLeafletContext} from '@react-leaflet/core';
import L from 'leaflet';

export const MyComponent = (props) => {
  const context = useLeafletContext();
  const control = L.control.Extend({
    //...options    
  });

  React.useEffect(() => {
    const container = context.layerContainer || context.map;
    container.addControl(control);

    return () => {
      container.removeControl(control);
    };
  });

  return null;
};
Run Code Online (Sandbox Code Playgroud)

这是自定义地图组件,您可以在其中使用之前创建的组件。

//MyMapComponent.jsx
import React from 'react';
import {MapContainer, TileLayer} from 'react-leaflet';
import {MyComponent} from './MyComponent';

export const MyMapComponent = (props) => {
  return (
    <MapContainer>
      <TileLayer url="whateverLayerURL" />
      <MyComponent {...props} />
    </MapContainer>
  );
};
Run Code Online (Sandbox Code Playgroud)