如何在 React Leaflet 中使用 onEachCountry 刷新 GeoJSON choropleth?

如何解决如何在 React Leaflet 中使用 onEachCountry 刷新 GeoJSON choropleth?

我是 JS、React 和 Leaflet 的新手,但我认为到目前为止我已经做到了。 我有一个正确显示咖啡信息的 choropleth。不幸的是,当我更改 onEachCountry 中的数据时,更改不会反映出来,因为这不是一个状态。也许我可以以某种方式使 onEachCountry 循环中的每一层成为一个状态?或者我可以在 JSX 中调用一些简单的刷新选项吗?

我试过对 onEachCountry 使用 useEffect,我也试过控制台日志并且数据正在更新,只是没有显示。其他传单挂钩在更改时似乎更容易更新。

非常感谢任何帮助。

import React,{ useState,useEffect } from "react";
import { MapContainer,GeoJSON,TileLayer } from "react-leaflet";
import "leaflet/dist/leaflet.css";
import "./ChoroMap.css";
import NavBarCountry from "../NavBarCountry";

// from Choro
const ChoroMap = ({ countries,coffees,onChangeLegend }) => {
  const [selectedStat,setSelectedStat] = useState("Producers");

  useEffect(() => {
    onEachCountry();
  },[selectedStat]);

  const onProducersClick = function () {
    onChangeLegend("Producers");
    setSelectedStat("Producers");
  };

  const onExportersClick = function () {
    onChangeLegend("Exporters");
    setSelectedStat("Exporters");
  };

  const onFarmsClick = function () {
    onChangeLegend("Farms");
    setSelectedStat("Farms");
  };


  function legend(stat,comparisonArray) {
    if (stat >= comparisonArray[0]) {
      return "#741f1f";
    } else if (stat >= comparisonArray[1] && stat < comparisonArray[0]) {
      return "#9c2929";
    } else if (stat >= comparisonArray[2] && stat < comparisonArray[1]) {
      return "#d75e5e";
    } else if (stat >= comparisonArray[3] && stat < comparisonArray[2]) {
      return "#c57979";
    } else if (stat >= 0 && stat < comparisonArray[3]) {
      return "#f1b1b1";
    }
  }

  function stripNumber(numberString) {
    const number = Number(numberString.replace(/[^\d.-]/g,""));
    return number;
  }

const onEachCountry = (country,layer) => {
if (country) {
  // defaults
  layer.options.fillOpacity = 1;
  layer.options.weight = 0.6;
  layer.options.color = "white";

      // country name from JSON
      const name = country.properties.ADMIN;

      const countryObj = coffees.find((coffee) => coffee.country === 
name);
      if (countryObj != null) {
        if ((selectedStat == "Producers")) {
          layer.bindPopup(`${name} 
${countryObj.production_volume}`);
          const productionVol = 
stripNumber(countryObj.production_volume);
          const foundColor = legend(
            productionVol,[10_000_000,5_000_000,2_000_000,500_000]
          );
          layer.options.fillColor = foundColor;
        }
        else if ((selectedStat == "Exporters")) {
            layer.bindPopup(`${name} ${countryObj.export_volume}`);
            const exportVol = stripNumber(countryObj.export_volume);
            const foundColor = legend(
              exportVol,500_000]
            );
            layer.options.fillColor = foundColor;
          }
        else if ((selectedStat == "Farms")) {
        layer.bindPopup(`${name} ${countryObj.number_of_farms}`);
        const numberOfFarms = 
stripNumber(countryObj.number_of_farms);
        const foundColor = legend(
            numberOfFarms,[5,10,15,20]
        );
        layer.options.fillColor = foundColor;
        }
        console.log('onEachCountry',layer.options.fillColor)
      }
    }
  };

  return (
    <div>
      <NavBarCountry
        onProducersClick={onProducersClick}
        onExportersClick={onExportersClick}
        onFarmsClick={onFarmsClick}
      />
      <MapContainer
        className="map"
        attributionControl={false}
        zoom={2.5}
        center={[10,10]}
      >
        
        <GeoJSON data={countries} onEachFeature={onEachCountry}/>
      </MapContainer>
    </div>
  );
};

export default ChoroMap;

解决方法

我试着理解你的问题,如果你只是想在地图中刷新你的 geoJSON 样式,而不是使用 choropleth,你最好试试这个。它更灵活,可以像 choropleth 一样动态

首先,我建议您使用类组件而不是使用函数并将您的 react-leaflet 版本更改为 2.7.0。这是因为我使用那个版本并且它的工作非常好。而且就我在 react-leaflet 的经验而言,没有太多讨论是谈论新版本,这就是为什么我建议您使用 2.7.0

数据

这将帮助您设置将在 WebGIS 中显示的 geojson 文件

<GeoJSON
    data={this.state.isMyGeoJSON}
/>

onEachFeature

用于设置每次对图层或特征进行操作时将调用的所有函数。我建议你在某个地方把它做成箭头函数,因为以后有很多函数可以在 onEachFeature 上调用。举个例子

<GeoJSON
    onEachFeature={this.onEachFeature}
/>

将此 onEachFeature 函数放在 render() 之前{

onEachFeature = (feature,layer) => {
    console.log(fetaure) //array of feature
    console.log(layer) //array of layer
    console.log(layer.feature) //array of feature
    //you must remember,feature is part of layer,so it's up to you how to call it later

layer.on({
    mouseover : this.onMouseOver,mouseout : this.onMouseOut,mouseclick : this.onMouseClick
})

//i will show you example of onMouseOver
onMouseOver = (event) => {
    event.target.setStyle({
        color : "yellow"
    })

render(){
...

正如您在那里看到的,有一个示例如何更改颜色,但是如果您想单击某个按钮并更改地图的颜色,该怎么办。这简单!首先,我再次建议您将默认样式放在 onEachFeature 中。为什么?因为我通常使用我的 GeoJSON 样式作为我的动态样式,让我举个例子

 //add this inside your onEachFeature for example
 onEachFeature = (feature,layer) => {
     layer.options.color : "blue" //change line all layer line color to blue,this work beacuse onEachFeature is loop function that are calling all layer one by one,so this thing will help you to change all your layer line color options to blue
     //still confused? try to call console.log(layer.options) for experiment
 }

该图层选项可以由您的 layer.onMouse 更改。但是如果我们想用地图外的按钮来改变它呢?或任何功能?你可以试试这个!

风格

这里应该是您放置默认样式的地方,但在本示例中,让我告诉您如何使您的默认样式动态化。如果我记得,有人在某个论坛上这样说,“如果你想改变它的风格,GeoJSON 中的样式就可以与函数调用一起使用”。然后我创建了这样的实验。

<GeoJSON
    style={this.stateMapTheme}
/>

在我的 this.state 里面我是这样写的

this.state = {
    mapTheme : this.firstStyle
}

让我们看看,我们要改变这个fillColor,因为我们已经在onEachFeature里面设置了默认颜色为蓝色,所以让我们做两个例子

//example of using data with if else
firstStyle(feature){
if (data < 20){
    return{
        fillColor : "red"
    }
} else {
    return{
        fillColor: "660000" //dark red
}


secondStyle(feature){
    return{
        fillColor : "green"
    }
}

在地图之外的某个地方创建 div

<div onClick={()=> {this.setState({mapTheme : this.secondStyle}) }}>green</div>
<div onClick={()=> {this.setState({mapTheme : this.firstStyle}) }}>red</div>

如果您想了解有关 react-leaflet 的更多信息,可以查看此信息,这将帮助您根据数据更改颜色 Medium React-Leaft by Deddy Setiawan

react-leaflet 示例的结果可以检查 here

如果您仍然无法理解我的解决方案,请让我从评论部分帮助您

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-
参考1 参考2 解决方案 # 点击安装源 协议选择 http:// 路径填写 mirrors.aliyun.com/centos/8.3.2011/BaseOS/x86_64/os URL类型 软件库URL 其他路径 # 版本 7 mirrors.aliyun.com/centos/7/os/x86
报错1 [root@slave1 data_mocker]# kafka-console-consumer.sh --bootstrap-server slave1:9092 --topic topic_db [2023-12-19 18:31:12,770] WARN [Consumer clie
错误1 # 重写数据 hive (edu)&gt; insert overwrite table dwd_trade_cart_add_inc &gt; select data.id, &gt; data.user_id, &gt; data.course_id, &gt; date_format(
错误1 hive (edu)&gt; insert into huanhuan values(1,&#39;haoge&#39;); Query ID = root_20240110071417_fe1517ad-3607-41f4-bdcf-d00b98ac443e Total jobs = 1
报错1:执行到如下就不执行了,没有显示Successfully registered new MBean. [root@slave1 bin]# /usr/local/software/flume-1.9.0/bin/flume-ng agent -n a1 -c /usr/local/softwa
虚拟及没有启动任何服务器查看jps会显示jps,如果没有显示任何东西 [root@slave2 ~]# jps 9647 Jps 解决方案 # 进入/tmp查看 [root@slave1 dfs]# cd /tmp [root@slave1 tmp]# ll 总用量 48 drwxr-xr-x. 2
报错1 hive&gt; show databases; OK Failed with exception java.io.IOException:java.lang.RuntimeException: Error in configuring object Time taken: 0.474 se
报错1 [root@localhost ~]# vim -bash: vim: 未找到命令 安装vim yum -y install vim* # 查看是否安装成功 [root@hadoop01 hadoop]# rpm -qa |grep vim vim-X11-7.4.629-8.el7_9.x
修改hadoop配置 vi /usr/local/software/hadoop-2.9.2/etc/hadoop/yarn-site.xml # 添加如下 &lt;configuration&gt; &lt;property&gt; &lt;name&gt;yarn.nodemanager.res