React Leaflet V3自定义控件

时间:2020-07-17 04:31:52

标签: react-leaflet

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

使用钩子完全重写。

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

基本控制示例

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;

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

我想在React / JSX / JS中编写此层控件,我不想完全使用html即L.Control并使用传单domutil来完全构建它,因为无论如何我的反应样式都无法使用,提供对我的redux存储的受限访问。因此,我试图通过基本的控件(例如react-leaflet-control的工作方式)来门户组件

我以正确的方式来处理吗?我只是绕圈自动取款机,试图使它以一种很好的方式工作。我快要把一个React组件作为地图的子级渲染并将位置设置为绝对位置了(我知道这是错误的方法,但确实可以做到)

<MapContainer>
  <ReactComponent />
</MapContiner>

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

3 个答案:

答案 0 :(得分:3)

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

依赖版本:

"react-leaflet": "^3.0.5",
"leaflet": "^1.7.1",

这是一个扩展 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;
};

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

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

答案 1 :(得分:3)

这可以使用 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)
);

答案 2 :(得分:-1)

我更新了答案。不确定是否对您有帮助,但希望它可以为您提供提示。

我从here的普通Leaflet示例中模拟了该示例,该示例在地图的左下方添加了一个控件。

import { MapContainer, TileLayer } from 'react-leaflet';
import { useLeafletContext } from '@react-leaflet/core'
import L from 'leaflet';
import {useEffect} from 'react'

function CustomControl(props) {
    const context = useLeafletContext()

    L.Control.Watermark = L.Control.extend({
        onAdd: function (map) {
            var img = L.DomUtil.create('img');

            img.src = './logo.png';
            img.style.width = '200px';

            return img;
        },

        onRemove: function (map) {
            // Nothing to do here
        }
    });

    L.control.watermark = function (opts) {
        return new L.Control.Watermark(opts);
    }

    useEffect(() => {
        const container = context.layerContainer || context.map

        const control = L.control.watermark({ position: props.position })
        container.addControl(control)

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

    return null
}


function MapCompenent() {

    return (
        <MapContainer center={[51.505, -0.09]} zoom={13} scrollWheelZoom={true} className='map'>
            <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"/>
           
            {/* the custom control */}
            <CustomControl position="bottomleft"></CustomControl>
        </MapContainer>
    )
}

Demo Screenshot

相关问题