首页 > 解决方案 > 在并排组件内限制对 React 中的 Leaflet TileLayers 的访问

问题描述

在一个显示地图的 React 应用程序上,我使用Leaflet-side-by-side插件(我按照这个线程的答案)做了一个并排比较器,它本身就可以正常工作。

但是,有些地图不是免费的,我想限制对它们的访问(并阻止对这些图块的请求)。现在,我已经做到了,除非您输入正确的密码,否则瓷砖不会显示。所以基本上,我需要在渲染后更新锁定的 TileLayer。当我使用 react-leaflet 时,我只是在密码匹配时使用 setUrl 来更新 TileLayer:

const LockedLayer = ({ lockedUrl, attribution }) => {
  const pwd = Config.PWD;
  const [inputPwd, setInputPwd] = useState(null);

  const tileLayerRef = useRef(null);

  useEffect(() => {
    if (pwd === inputPwd) {
      tileLayerRef.current.setUrl(lockedUrl);
    }
  });

  return <TileLayer attribution={attribution} url="" ref={tileLayerRef} />;
};

效果很好。

但是对于并排传单,我需要使用本机传单,它的行为不一样。应用于由 L.tileLayer 创建的 TileLayer 的相同代码无效,即使 URL 已正确更新,尽管图层发生更改,地图也不会更新其内容(因为它位于钩子内,我假设)。就像我提到的,在添加我自己的层之前,我从一个线程复制粘贴了代码,如下所示:

import "leaflet-side-by-side";
...

const Map = () => {
  useEffect(() => {
    const map = L.map("map").setView([51.505, -0.09], 13);

    const osmLayer = L.tileLayer("http://{s}.tile.osm.org/{z}/{x}/{y}.png", { attribution: 'OSM' }).addTo(map);

    const lockedLayer = LeafletLockedLayer(
      "PROTECTED_URL", { attribution: 'credits'}
    ).addTo(map);

    L.control.sideBySide(lockedLayer, osmLayer).addTo(map);
  }, []);

  return <div id="map" />;
};
const LeafletLockedLayer = ({ lockedUrl, attribution }) => {
  const pwd = Config.PWD;
  const [inputPwd, setInputPwd] = useState(null);

  const tileLayer = L.tileLayer("", { attribution: attribution });

  useEffect(() => {
    if (pwd === inputPwd) {
      tileLayer.setUrl(lockedUrl);
    }
  });

  return tileLayer;
};

到目前为止,我没有成功地尝试过:

我正在寻找的是一种并排更新和重绘传单中的图层的方法,另一种限制对某些图层的访问的方法,或者是允许我使用 react-leaflet 的插件的替代方法。

提前感谢您的任何想法!

标签: reactjsleafletreact-leaflet

解决方案


在尝试了不同的配置之后,我认为让图层在更新后再次触发其请求的唯一方法是在useEffect. 我写的LeafletLockedLayer不能在里面使用useEffect(因为它使用了钩子),但是一个简单的解决方法是useEffect用一个临时的替换它自己的setTimeout/ setInterval。虽然我宁愿不使用这些,但我没有时间寻找更好的解决方案,而且读取密码所需的时间也比加载磁贴要短。

这是一个LeafletLockedLayer可以在与useEffect地图相同的内部创建的工作,就像它的意思一样:

const LeafletLockedLayer = ({ lockedUrl, attribution }) => {
  const storedPwd = Config.layersPwd;
  let pwd = null;

  const tileLayer = L.tileLayer("", { attribution: attribution });

  const interval = setInterval(() => updateLayer(), 100);
  const updateLayer = () => {
    if (pwd === storedPwd) {
      tileLayer.setUrl(lockedUrl);
      clearInterval(interval);
    }
  };

  return tileLayer;
};

推荐阅读