首先需要写一个组件:
- 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>
- ))}
-