Search code examples
mapsopenlayersshapefile

Adding a ShpFile tilts the map


I'm using OpenLayer with react. I'm display a map as a baselayer and then I'm adding a GeoTiff on top of it. After that the user can also add a shape file (zip) as another layer and it is working properly the only problem is that after addding the shape file it tilts the whole map. Is there any way to avoid it? Here are some screen shot

Before Adding Shapefile

After adding shape file

here's my code

  const [shape, setShape] = useState(null);
  const [layer, setLayer] = useState(null);
  const [showShape, setShowShape] = useState(false);
  const [map, setMap] = useState(null);

  async function loadShapefile(src) {
    // Load the shapefile data
    const content = await shp(src);
    const geoJSON = new GeoJSON();
    const features = geoJSON.readFeatures(content);
    const projection = geoJSON.readProjection(content);

    // Create a vector layer to display the features
    const vectorSource = new VectorSource({ features });

    const vectorLayer = new VectorLayer({ source: vectorSource });
    return [vectorLayer, vectorSource, projection];
  }



  const renderShp = async () => {
    setShowLoader(true);
    const [layer, vectorSource, projection] = await loadShapefile(shape);

    map.addLayer(layer);
    const extent = vectorSource.getExtent();
    // Transform the extent from the Shapefile projection to the map projection
    const viewConfig = {
      projection,
      center: getCenter(extent),
      zoom: 2
    };

    map.setView(new View(viewConfig));

    map.getView().fit(extent, {
      padding: [50, 50, 50, 50], // Adjust the padding as desired
    });
    setShowLoader(false);
  };

  useEffect(() => {
    // Remove any existing vector layers from the map
    if (!map) return;
    map.getLayers().forEach((existingLayer) => {
      if (existingLayer instanceof VectorLayer) {
        map.removeLayer(existingLayer);
      }
    });
    if (shape) renderShp();
    else {
      // set view back to the geotiff
      map.setView(layer.getSource().getView().then(getViewConfig(map)));
    }
  }, [shape]);


I'm getting shp function from this script https://unpkg.com/shpjs@latest/dist/shp.js


Solution

  • You should read the GeoJSON data into the current view projection

     async function loadShapefile(src) {
        // Load the shapefile data
        const content = await shp(src);
        const geoJSON = new GeoJSON({featureProjection: map.getView().getProjection()});
        const features = geoJSON.readFeatures(content);
    
        // Create a vector layer to display the features
        const vectorSource = new VectorSource({ features });
    
        const vectorLayer = new VectorLayer({ source: vectorSource });
        return [vectorLayer, vectorSource];
      }
    
      const renderShp = async () => {
        setShowLoader(true);
        const [layer, vectorSource] = await loadShapefile(shape);
    
        map.addLayer(layer);
        const extent = vectorSource.getExtent();
    
        map.getView().fit(extent, {
          padding: [50, 50, 50, 50], // Adjust the padding as desired
        });
        setShowLoader(false);
      };