You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将基于jQuery的HighChart地图转换为React组件

Highcharts肯尼亚选举地图 jQuery 转 React 实现方案

项目基础信息

  • 原实现为基于jQuery的Highcharts肯尼亚总统选举地图,点击对应郡县可弹出选区两党得票占比饼图
  • 现有可用资源:
    • 郡县选举统计JSON数据(当前为硬编码格式,后续可直接替换为API接口返回数据)
    • 原版本的数据映射、配色、交互逻辑
    • Highcharts相关依赖资源

原jQuery核心实现代码

$(function() {
  var json = [{
    "name": "Busia",
    "registered": "251305",
    "UDA": "0",
    "Azimio": "0",
    "value": "-5"
  },{
    "name": "Wajir",
    "registered": "118091",
    "UDA": "8",
    "Azimio": "7",
    "value": "-2"
  }]

  function init() {

    function pointClick(json) {
      var row = this.options.row,
        $div = $('<div></div>')
        .dialog({
          title: ([this.name]),
          width: 400,
          height: 300
        });

      window.chart = new Highcharts.Chart({
        chart: {
          renderTo: $div[0],
          type: 'pie',
          width: 370,
          height: 240
        },
        title: {
          text: null
        },
        series: [{
          name: 'Votes',
          data: [{
            name: 'Azimio',
            color: '#0200D0',
            y: Number(this.Azimio)
          }, {
            name: 'UDA',
            color: '#C40401',
            y: Number(this.UDA)
          }],
          dataLabels: {
            format: '<b>{point.name}</b> {point.value:.1f}%'
          }
        }]
      });
    }

    // 初始化地图
    $('#presidential').highcharts('Map', {
      title: {
        text: 'Presidential Electoral Map <em>(Kenya)</em>'
      },
      legend: {
        title: {
          text: 'Political Affiliation' 
        }
      },
      credits: {
        enabled: false
      },
      tooltip: {
        valueSuffix: 'Margin'
      },
      mapNavigation: {
        enabled: true,
        enableButtons: false
      },

      colorAxis: {

        dataClasses: [{
          from: 0.0000001,
          to: 100,
          color: '#C40401',
          name: 'UDA'
        }, {
          from: -100,
          to: -0.00000001,
          color: '#0200D0',
          name: 'Azimio'
        }, {
          from: 0,
          to: 0,
          color: '#C0C0C0',
          name: 'Battle Ground(s)'
        }]
      },
      series: [{
        name: 'By County Difference',
        point: {
          events: {
            click: pointClick
          }
        },
        "type": "map",
        "joinBy": ['name', 'name'],
        "data": $.each(json, function() {}),
        "mapData": [{
          "name": "Busia",
          "path": "M40,-534,43,-533,46,-532L46,-530L44,-528,44,-525C44,-525,41,-520,41,-520L40,-516,40,-513,41,-511C41,-511,44,-512,43,-509,43,-506,44,-504,44,-504L38,-499,38,-497,44,-495,45,-493,41,-489,41,-486L36,-486L34,-487,30,-488,28,-487,25,-484,22,-484,20,-486,18,-483,16,-481,15,-478,14,-476L14,-473L15,-471,14,-469L12,-469L10,-467,9,-464,10,-459C10,-459,9,-458,7,-457,5,-456,5,-455,5,-455L3,-459,0,-462,0,-465,2,-470,2,-474L2,-478L5,-481,8,-486,10,-491,13,-493L13,-495L12,-499,13,-503,15,-506,15,-510,16,-513C16,-513,19,-516,20,-517,21,-517,24,-519,24,-519L27,-519,28,-519,31,-520L31,-524L32,-526,33,-527,34,-531,35,-532z"
        },
        }]
      }, {
        "type": "mapline",
        "data": [{
          "name": "path5072",
          "path": "M443,-449Z"
        }]
      }]
    });
  }
  init()
});

之前使用React封装库失败的核心原因

  • 未正确注册Highcharts地图模块:直接使用通用Highcharts包没有加载map模块,导致map类型图表无法识别渲染
  • 原jQuery代码存在数据绑定错误:"data": $.each(json, function() {})写法无效,$.each返回的是遍历对象本身不是选举数据数组,导致地图数据为空
  • 直接照搬jQuery UI Dialog的DOM操作逻辑:在React中直接手动创建DOM节点挂载饼图,和React的虚拟DOM渲染逻辑冲突,导致弹窗、饼图渲染异常

React版本正确实现步骤

  1. 安装对应依赖
npm install highcharts highcharts-react-official
  1. 组件内注册地图模块,不要遗漏模块加载
  2. 修正原代码的数据绑定错误,直接传入选举数据数组,不要套无效的$.each遍历
  3. 替换jQuery DOM操作弹窗逻辑,用React状态控制弹窗显隐、传递点击的选区数据,弹窗内用HighchartsReact组件渲染饼图

核心实现代码示例

import { useState } from 'react';
import Highcharts from 'highcharts';
import MapModule from 'highcharts/modules/map';
import HighchartsReact from 'highcharts-react-official';
// 导入完整的肯尼亚地图路径数据(替换为本地完整mapData即可)
import kenyaMapData from './kenya-map-data';

// 注册地图模块
MapModule(Highcharts);

const ElectoralMap = () => {
  // 选举数据,后续可替换为接口请求获取
  const electionData = [
    {
      "name": "Busia",
      "registered": "251305",
      "UDA": "0",
      "Azimio": "0",
      "value": "-5"
    },{
      "name": "Wajir",
      "registered": "118091",
      "UDA": "8",
      "Azimio": "7",
      "value": "-2"
    }
  ];

  // 弹窗状态控制
  const [modalOpen, setModalOpen] = useState(false);
  const [selectedCounty, setSelectedCounty] = useState(null);

  // 地图配置,绝大多数配置和原jQuery版本完全一致
  const mapOptions = {
    title: {
      text: 'Presidential Electoral Map <em>(Kenya)</em>'
    },
    legend: {
      title: {
        text: 'Political Affiliation' 
      }
    },
    credits: {
      enabled: false
    },
    tooltip: {
      valueSuffix: 'Margin'
    },
    mapNavigation: {
      enabled: true,
      enableButtons: false
    },
    colorAxis: {
      dataClasses: [{
        from: 0.0000001,
        to: 100,
        color: '#C40401',
        name: 'UDA'
      }, {
        from: -100,
        to: -0.00000001,
        color: '#0200D0',
        name: 'Azimio'
      }, {
        from: 0,
        to: 0,
        color: '#C0C0C0',
        name: 'Battle Ground(s)'
      }]
    },
    series: [{
      name: 'By County Difference',
      point: {
        events: {
          click: function() {
            // this指向当前点击的选区点数据
            setSelectedCounty(this);
            setModalOpen(true);
          }
        }
      },
      type: "map",
      joinBy: ['name', 'name'],
      data: electionData, // 修正原$.each的错误写法,直接传数据数组
      mapData: kenyaMapData
    }, {
      type: "mapline",
      data: [{
        "name": "path5072",
        "path": "M443,-449Z"
      }]
    }]
  };

  // 饼图配置
  const pieOptions = selectedCounty ? {
    chart: {
      type: 'pie',
      width: 370,
      height: 240
    },
    title: {
      text: null
    },
    series: [{
      name: 'Votes',
      data: [{
        name: 'Azimio',
        color: '#0200D0',
        y: Number(selectedCounty.Azimio)
      }, {
        name: 'UDA',
        color: '#C40401',
        y: Number(selectedCounty.UDA)
      }],
      dataLabels: {
        format: '<b>{point.name}</b> {point.value:.1f}%'
      }
    }]
  } : {};

  return (
    <div>
      <div id="presidential">
        <HighchartsReact
          highcharts={Highcharts}
          constructorType={'mapChart'}
          options={mapOptions}
        />
      </div>
      {/* 自定义弹窗,替换原jQuery UI Dialog */}
      {modalOpen && selectedCounty && (
        <div className="modal-mask" onClick={() => setModalOpen(false)}>
          <div className="modal-content" onClick={e => e.stopPropagation()}>
            <div className="modal-header">
              <span>{selectedCounty.name}</span>
              <button onClick={() => setModalOpen(false)}>×</button>
            </div>
            <HighchartsReact
              highcharts={Highcharts}
              options={pieOptions}
            />
          </div>
        </div>
      )}
    </div>
  )
}

export default ElectoralMap;

注意事项

  • 完整的肯尼亚郡县地图路径数据直接替换示例中kenyaMapData的导入即可,不需要修改其他配置
  • 弹窗样式可根据需求自行编写CSS,不需要依赖jQuery UI
  • 如果后续需要对接API,只需要把electionData改为useState管理的状态,在useEffect中请求接口赋值即可,其他逻辑不需要改动

内容的提问来源于stack exchange,提问作者Brian Otieno

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 00:39:44