当前位置: 首页 > 知识库问答 >
问题:

无法访问反应传单中的GeoJSON层

公冶鸣
2023-03-14

我使用React传单渲染传单贴图,使用GeoJSON组件渲染多边形。我正在尝试将多个多边形作为一个组同时拖动到一起。

我添加了传单。路径。拖动库并尝试重用此代码。我能够得到处于父状态的变换矩阵。如果我想用_transform方法将此矩阵应用于多个多边形,它不起作用。我认为原因是矩阵没有应用于正确的层,但我不知道如何解决这个问题。

代码沙盒。木卫一

一个pp.js

import React from "react";
import { MapContainer, GeoJSON, TileLayer } from "react-leaflet";
import { geoJson, latLngBounds } from "leaflet";
import "./styles.css";
import "leaflet/dist/leaflet.css";

import { GeoJsonContainer } from "./GeoJsonContainer";

const objects = [
  {
    polygon: {
      type: "FeatureCollection",
      features: [
        {
          type: "Feature",
          properties: {},
          geometry: {
            type: "Polygon",
            coordinates: [
              [
                [-104.98569488525392, 39.63431579014969],
                [-104.98569488525392, 39.64165260123419],
                [-104.97161865234376, 39.64165260123419],
                [-104.97161865234376, 39.63431579014969]
              ]
            ]
          }
        }
      ]
    }
  },
  {
    polygon: {
      type: "FeatureCollection",
      features: [
        {
          type: "Feature",
          properties: {},
          geometry: {
            type: "Polygon",
            coordinates: [
              [
                [-105.02964019775392, 39.6206315500488],
                [-105.02964019775392, 39.65685252543906],
                [-104.99067306518556, 39.65685252543906],
                [-104.99067306518556, 39.6206315500488]
              ]
            ]
          }
        }
      ]
    }
  }
];

const getPolygonPointFromBounds = (latLngBounds) => {
  const center = latLngBounds.getCenter();
  const latlngs = [];

  latlngs.push(latLngBounds.getSouthWest()); //bottom left
  latlngs.push({ lat: latLngBounds.getSouth(), lng: center.lng }); //bottom center
  latlngs.push(latLngBounds.getSouthEast()); //bottom right
  latlngs.push({ lat: center.lat, lng: latLngBounds.getEast() }); // center right
  latlngs.push(latLngBounds.getNorthEast()); //top right
  latlngs.push({
    lat: latLngBounds.getNorth(),
    lng: latLngBounds.getCenter().lng
  }); //top center
  latlngs.push(latLngBounds.getNorthWest()); //top left
  latlngs.push({
    lat: latLngBounds.getCenter().lat,
    lng: latLngBounds.getWest()
  }); //center left

  return latlngs;
};

export default function App() {
  const [matrix, setMatrix] = React.useState(null);

  let newBounds = [];
  let selectBoundingBox = [];

  objects.forEach((building) => {
    const polygonBounds = geoJson(building.polygon).getBounds();
    newBounds = [...newBounds, polygonBounds];
  });

  const polygonPoints = getPolygonPointFromBounds(latLngBounds(newBounds));
  const convertedData = polygonPoints.map((point) => [point.lng, point.lat]);
  convertedData.push([polygonPoints[0].lng, polygonPoints[0].lat]);
  selectBoundingBox = convertedData;

  let selectBoxData = null;

  if (selectBoundingBox) {
    selectBoxData = {
      type: "FeatureCollection",
      features: [
        {
          type: "Feature",
          properties: {},
          geometry: {
            type: "Polygon",
            coordinates: [selectBoundingBox]
          }
        }
      ]
    };
  }

  const handleFeature = (layer) => {
    layer.makeDraggable();
    layer.dragging.enable();

    layer.on("drag", function (e) {
      setMatrix(layer.dragging._matrix);
    });
  };

  return (
    <MapContainer center={[39.63563779557324, -104.99234676361085]} zoom={12}>
      <TileLayer
        attribution='&amp;copy <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
        url="https://{s}.tile.osm.org/{z}/{x}/{y}.png"
      />
      {objects.map((object, i) => (
        <GeoJsonContainer data={object} key={i} matrix={matrix} />
      ))}
      <GeoJSON
        data={selectBoxData}
        style={() => ({
          color: "green",
          weight: 3,
          opacity: 0.5
        })}
        draggable={true}
        onEachFeature={(feature, layer) => handleFeature(layer)}
      ></GeoJSON>
    </MapContainer>
  );
}

GeoJsonContainer。js

import React from "react";
import { GeoJSON } from "react-leaflet";

require("leaflet-path-drag");

export const GeoJsonContainer = (props) => {
  const geoJSONRef = React.useRef(null);
  const layerRef = React.useRef(null);

  React.useEffect(() => {
    if (geoJSONRef?.current?._layers) {
      console.log("mount layers", geoJSONRef.current?._layers);
    }
  }, []);

  React.useEffect(() => {
    if (geoJSONRef?.current._layers && props.matrix) {
      console.log("transform layers", geoJSONRef.current._layers);
      const key = Object.keys(geoJSONRef.current._layers)[0];
      const geoJSONElementLayer = geoJSONRef.current._layers[key];
      if (geoJSONElementLayer) {
        console.log("geoJSONElementLayer", geoJSONElementLayer);
        console.log("layerRef.current", layerRef.current);
        geoJSONElementLayer._transform(props.matrix);
        layerRef.current._transform(props.matrix);
      }
    }
  }, [props.matrix]);

  const handleFeature = (layer) => {
    console.log("handleFeature layer", layer);
    layerRef.current = layer;
    layer.makeDraggable();
    layer.dragging.enable();
  };

  return (
    <GeoJSON
      ref={geoJSONRef}
      data={props.data.polygon}
      style={() => ({
        color: "#3388ff",
        weight: 3,
        opacity: 1
      })}
      dragging={true}
      onEachFeature={(feature, layer) => handleFeature(layer)}
    ></GeoJSON>
  );
};

共有1个答案

宗政松
2023-03-14

关于

如果我想用_变换方法将这个矩阵应用于多个多边形,它就不起作用了

这是React中的预期行为,因为矩阵prop需要是不可变的,这意味着每次发生更改时都需要传递一个新html" target="_blank">数组:

 layer.on("drag", function (e) {
   setMatrix([...layer.dragging._matrix]);
});

而不是:

layer.on("drag", function (e) {
   setMatrix(layer.dragging._matrix);
});

这样,GeoJsonContainer组件应该按预期重新渲染。

另一个问题涉及<代码>传单。路径。拖动插件,根据引用的线程,实际上dropdropend事件都需要被捕获才能正确应用转换,所以也许代替矩阵道具,引入一个转换道具要保留矩阵数组和一个标志,以确定是否触发了dropenddropend事件:

const handleFeature = (layer) => {
    layer.makeDraggable();
    layer.dragging.enable();

    layer.on("drag", function (e) {
      setTransform({matrix: layer.dragging._matrix, "end": false});
    });

    layer.on("dragend", function (e) {
      setTransform({matrix: layer.dragging._matrix, "end": true});
    });
  };

并将其传递到GeoJsonContainer组件以应用几何体变换:

React.useEffect(() => {

    if (props.transform) {
      geoJSONRef.current.eachLayer((layer) => {
        if (props.transform.end) dragDropTransform(layer);
        else __dragTransform(layer);
      });
    }
}, [props.transform]);

在哪里

  function __dragTransform(layer) {
      layer._transform(props.transform.matrix);
   }

   function dragDropTransform(layer) {
     layer.dragging._transformPoints(props.transform.matrix);
     layer._updatePath();
     layer._project();
     layer._transform(null);
   }

更新了现场演示

可能的改进:

  • 在所提供的示例中,JSON层的两个实例被实例化,可能要考虑创建一个“代码> GEJJSON 的单个实例,并应用每个几何体的样式?”李>

解决方案改进建议

在提供的示例中,实例化了两个层:

App组件中

  • GeoJSON层,它呈现单个外部几何(多边形)

GeoJsonContainer组件中,选择另一个

  • GeoJSON层,该层依次呈现两个内部几何体(多边形)

合并两个GeoJSON对象如何,如下所示:

const dataSource = {...selectBoxData,...objects[0],...objects[1]}    

并创建一个单独的层:

<GeoJSON data={dataSource}></GeoJSON>

这样可以避免对可拖动层进行两次初始化(重构重复代码)

 类似资料:
  • 问题内容: 这是我的文件上传脚本,出现以下错误 但是据此应该不会出错,因为我确定了索引。看来我无权访问$ _FILES数组,因为在收到此错误IVE之前,我一直遇到其他类似的错误,或者程序完全通过了if并直接进入else(未选择文件) 我知道该脚本是原始脚本,几乎不包含安全性,但是我只想让它先工作,然后再添加其他功能,例如最大文件大小或文件限制… :( 这是我正在使用的代码。 这是处理表格的PHP

  • 我有一个名为的组件,还有一个子组件名为。智利组件有一个名为的状态。我需要从AvailabiltyCalendar组件访问该状态并获取该状态值。我该怎么做呢。 可用压路机组件 DatePicker组件

  • JDK11+spring批处理 有人知道那些警告是什么意思吗: 警告:发生了非法的反射访问操作警告:org.springframework.cglib.core.reflectutils$1(jar:file:/users/boru/downloads/spcljr/build/libs/spcljr-0.0.1-snapshot.jar!/boot-inf/lib/spring-core-5.0

  • 接口说明 为了让用户设置的单体化、标绘、压平数据(点线面要素信息等)在下一次访问数据的时候,能正常查看,Wish3DEarth团队新增了单体化、标绘、压平数据的保存接口,最终访问相对应的文件,来加载设置好的属性信息。 存储的文件名如下 1:单体化 attach.geojson 2:标绘 draw.geojson 3:压平 flatten.geojson 如需调用,请访问 开发者文档 来查看详细的接

  • 问题内容: 这是一个测试类: 这是我的输出: 我缺少通过反射使注释可见的什么? 我是否仅需要检查它们的存在就需要注释处理器? 问题答案: 为了在运行时访问注释,它需要具有运行时的保留策略。 否则,注释将被丢弃,并且JVM无法识别它们。 有关更多信息,请参见此处。

  • 我试图理解下面的反应HOC; 下面是另一个组件; 具体来说我是想了解 如果它“DisplayTheCret”访问道具“secretToLife”或WrappedComponent?正确看待这一问题的方法是什么? “const WrappedComponent=withSecretToLife(displaytescret);”行位于“const displaytescret=props”行之后=

  • 问题内容: 我不明白“无法​​访问的代码”是什么意思? 在我的代码的最后一行中,它表示无法访问的代码。 } 问题答案: 这里的循环: 解析为,因为从未修改过的值。因此,(在您的情况下)之后出现的任何代码均被视为 无法访问 。

  • 我有一个超级简单的Java库伯内特斯Tomcat应用程序在库伯内特斯内部运行,我用在minikube上运行的JVM Jolokia代理安装了它。我正在尝试配置我的库伯内特斯部署,以便我可以在容器外部访问Jolokiaendpoint。当我试图从我的minikube IP上的容器外部访问http://127.0.0.1/jolokia/versionendpoint时,我收到一个连接被拒绝。 我已经