react d3使用循环显示多个地图

首先需要写一个组件:

import React, { useState, useEffect, useRef } from 'react';
import ChinaMap from 'moment';
import * as d3 from 'd3';
import chinaGeoJson from 'china-geojson/src/geojson/china.json';

const MyMapToShowResult = ({ realData }) => {
  const [data, setData] = useState({});
  const [loading, setLoading] = useState(true);
  const svgRef = useRef(null);
  const [hoveredProvince, setHoveredProvince] = useState(null);

  useEffect(() => {
    const backgroundColor = 'blue';
    const svg = d3.select(svgRef.current);

    svg.style('background-color', backgroundColor);
    let isMounted = true;

    const width = 780;
    const height = 580;

    const projection = d3.geoMercator()
      .center([105, 38])
      .scale(600)
      .translate([width / 2, height / 2]);

    const path = d3.geoPath().projection(projection);
    const features = JSON.parse(JSON.stringify(chinaGeoJson.features));
    //const realData = [
    //  { province: '北京', emission: 500 },
    //  { province: '上海', emission: 200 },
    //  { province: '台湾', emission: 400 },
    //  { province: '青海', emission: 200 },
    //  { province: '辽宁', emission: 300 },
    //  { province: '黑龙江', emission: 100 },
    //];

    features.forEach((feature, i) => {
      // 在 realData 中查找对应省份的数据
      const provinceData = realData.find(data => data.province === feature.properties.name);
      // 如果找到对应省份的数据,则将真实的数量赋给 emission 属性
      if (provinceData) {
        feature.properties.emission = provinceData.emission;
      } else {
        feature.properties.emission = 0;
      }
    });
    console.log('== 省份数据:', features);

    svg.selectAll('*').remove();
    svg.append('g')
      .attr('transform', `translate(${width / 2},${height / 2})`)
      .call(projection);
    svg.selectAll('path')
      .data(features)
      .join('path')
      .attr('d', path)
      .transition()
      .attr('fill-opacity', 0.8)
      .style('stroke', 'black')
      .style('stroke-width', '1px')
      .attr('data-tip', (d, i) => { return d.properties.name + " : " + d.properties.emission; })
      .attr('fill', (d, i) => {
        const colorScale = d3.scaleSequential()
          .interpolator(d3.interpolateRgb('#ffffff', '#008000'))
          .domain([0, d3.max(features, d => d.properties.emission)]);

        return colorScale(d.properties.emission);
      });

    // 创建比色卡
    const legendWidth = 200;
    const legendHeight = 20;
    const legendPadding = 10;
    const legend = svg.append('g')
      .attr('transform', `translate(${width - legendWidth - legendPadding},${height - legendHeight - legendPadding})`);

    const colorScale = d3.scaleSequential()
      .interpolator(d3.interpolateRgb('#ffffff', '#008000'))
      .domain([0, d3.max(features, d => d.properties.emission)]);

    console.log('== 比色卡前,省份数据:', features);
    const legendXScale = d3.scaleLinear()
      .domain([0, d3.max(features, d => d.properties.emission)])
      .range([0, legendWidth]);
    // 根据需要设置刻度数量
    const legendXAxis = d3.axisBottom(legendXScale)
      .ticks(5);

    legend.append('g')
      .attr('class', 'legend-axis')
      .attr('transform', `translate(0, ${legendHeight})`)
      .call(legendXAxis);

    const legendGradient = legend.append('linearGradient')
      .attr('id', 'legend-gradient')
      .attr('gradientUnits', 'userSpaceOnUse')
      .attr('x1', 0)
      .attr('x2', legendWidth)
      .selectAll('stop')
      .data(colorScale.ticks().map((t, i, n) => ({
        offset: `${100 * i / n.length}%`,
        color: colorScale(t)
      })))
      .join('stop')
      .attr('offset', d => d.offset)
      .attr('stop-color', d => d.color);

    legend.append('rect')
      .attr('x', 0)
      .attr('y', -legendHeight / 2)
      .attr('width', legendWidth)
      .attr('height', legendHeight)
      .style('fill', 'url(#legend-gradient)');


  }, [data]);



  return (
    <div>
    <svg ref={svgRef} width="800" height="600"></svg>
    <div id="tooltip" style={{ display: 'none', position: 'absolute', backgroundColor: 'white', padding: '5px', borderRadius: '5px', boxShadow: '0 2px 5px rgba(0, 0, 0, 0.3)', zIndex: '999' }}></div>
    {hoveredProvince && (
      <div id="tooltip" style={{ display: 'block', position: 'absolute', backgroundColor: 'white', padding: '5px', borderRadius: '5px', boxShadow: '0 2px 5px rgba(0, 0, 0, 0.3)', zIndex: '999', left: '10px', top: '10px' }}>
      {hoveredProvince}
      </div>
    )}
    </div>
  );
};

export default MyMapToShowResult;

然后在页面进行引用,并且传递数据给组件:

引入:

import MyMapToShowResult from "@/compontens/MyMapToShowResult";

渲染:(注意需要把realData声明赋值)

<MyMapToShowResult realData={realData}/

在循环中使用:

{data.map((item, index) => (
 <div key={index}>
   <p>map{index}</p>
   <MyMapToShowResult realData={realData}/>
 </div>
))}

                                  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值