Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
ReactJS D3-如何放大D3地理世界地图_Reactjs_D3.js - Fatal编程技术网

ReactJS D3-如何放大D3地理世界地图

ReactJS D3-如何放大D3地理世界地图,reactjs,d3.js,Reactjs,D3.js,我正在开发一个使用ReactJS的web应用程序。我在React组件中使用D3渲染了世界地图。它具有基本功能,例如每当单击世界地图中的某个国家时(因此“放大”),都会调整geoMercator().fitSize()。但是,我希望用户能够通过滚动鼠标滚轮放大自定义数量,但我不知道如何做到这一点。在谷歌在线搜索时,我遇到了d3缩放功能,但所有示例都是通过调整比例完成的,但我不知道如何将其应用于d3 geo,它似乎没有比例,只有投影 这是到目前为止我的代码 function GeoChart() {

我正在开发一个使用ReactJS的web应用程序。我在React组件中使用D3渲染了世界地图。它具有基本功能,例如每当单击世界地图中的某个国家时(因此“放大”),都会调整geoMercator().fitSize()。但是,我希望用户能够通过滚动鼠标滚轮放大自定义数量,但我不知道如何做到这一点。在谷歌在线搜索时,我遇到了d3缩放功能,但所有示例都是通过调整比例完成的,但我不知道如何将其应用于d3 geo,它似乎没有比例,只有投影

这是到目前为止我的代码

function GeoChart() {

    const svgRef = useRef();
    const wrapperRef = useRef();
    const [dimensions, setDimensions] = useState(useResizeObserver(wrapperRef));
    const [selectedCountry, setSelectedCountry] = useState(null);

    useEffect(() => {
        const svg = select(svgRef.current);
        const { width, height } = wrapperRef.current.getBoundingClientRect();

        const minProp = leadCount ? min(leadCount, count => count.count) : null
        const maxProp = leadCount ? max(leadCount, count => count.count) : null
        const colorScale = scaleLinear()
            .domain([minProp, maxProp])
            .range(["#ccc", "red"]);

        // projects geo-coordinates on a 2D plane
        const projection = geoMercator()
            .fitSize([width, height], selectedCountry || data)
            .precision(100);

        // takes geojson data,
        // transforms that into the d attribute of a path element
        const pathGenerator = geoPath().projection(projection);

        // render each country
        svg
            .selectAll(".country")
            .data(data.features)
            .join("path")
            .on("click", feature => {
                console.log(selectedCountry)
                setSelectedCountry(selectedCountry === feature ? null : feature);
            })
            .attr("class", "country")
            .transition()
            .attr("fill", feature => findLeadCount(feature.properties.name))
            .attr("d", feature => pathGenerator(feature))

}, [data, dimensions, selectedCountry]);

return (
        <div ref={wrapperRef} style={{ marginBottom: "2rem" }}>
            <svg id="geo-chart" ref={svgRef}></svg>
        </div>
) }

export default GeoChart;
function-art(){
const svgRef=useRef();
const wrapperRef=useRef();
const[dimensions,setDimensions]=useState(useResizeObserver(wrapperRef));
const[selectedCountry,setSelectedCountry]=useState(空);
useffect(()=>{
const svg=select(svgRef.current);
const{width,height}=wrapperRef.current.getBoundingClientRect();
const minProp=leadCount?min(leadCount,count=>count.count):null
const maxProp=leadCount?max(leadCount,count=>count.count):空
const colorScale=scaleLinear()
.domain([minProp,maxProp])
.范围([“#ccc”,“红色]);
//在二维平面上投影地理坐标
常量投影=几何算子()
.fitSize([宽度、高度],所选国家/地区| |数据)
.精度(100);
//获取geojson数据,
//将其转换为路径元素的d属性
const pathGenerator=geoPath().projection(projection);
//使每个国家
svg
.selectAll(“.country”)
.数据(数据.特征)
.join(“路径”)
.on(“单击”,功能=>{
console.log(已选择的国家/地区)
设置selectedCountry(selectedCountry==特征?空:特征);
})
.attr(“类别”、“国家”)
.transition()
.attr(“fill”,feature=>findLeadCount(feature.properties.name))
.attr(“d”,功能=>pathGenerator(功能))
},[数据、尺寸、所选国家/地区];
返回(
) }
出口艺术;
感谢所有的帮助,我是D3新手,因此可能有一些事情我不知道怎么做,请帮助我找到正确的方向,谢谢

我提供了两种通用的D3解决方案;React的适应应该相当简单。通过保持通用性,答案和代码片段更加清晰,尽管答案仍然冗长

坐标

在处理地理投影和缩放时,我们要处理几个坐标系:

  • 地理坐标(地球仪上的三维坐标,以度为单位)
  • 投影坐标(笛卡尔数据,以像素为单位,投影结果)
  • SVG/画布坐标(平移和缩放应用于投影坐标,例如通过
    SVG
    transform属性)
可以通过投影功能使用适当的平移和缩放,这样就不需要SVG/Canvas转换。例如,如果需要进一步放大地图,则将D3投影比例或SVG/画布比例加倍具有相同的效果。因此,通过确保投影参数的设置不需要设置SVG/Canvas变换,我们可以有效地消除对第三坐标系的考虑

如果我们想避免使用SVG/画布转换,我们将进行语义缩放:我们将根据更新的投影重新绘制所有数据。让投影来完成所有的工作

如果我们想要操纵SVG/Canvas转换来实现缩放,我们将进行几何缩放。这只需要对特征的初始绘制进行投影,然后使用SVG/Canvas转换移动已绘制的特征并根据需要调整其大小

两者都有不同的优点和缺点。我不会在这里与他们交谈,但我将展示如何实现这两个目标

语义缩放

对于您的用例,这可能是更容易实现的解决方案

我们可以使用
d3.zoom()
跟踪当前平移和缩放:

  let zoom = d3.zoom()
    .on("zoom", function() {
        let t = d3.event.transform;                 // get current zoom state
        projection.scale(t.k).translate([t.x,t.y]); // set scale and translate of projection.
        features.attr("d", path)                    // redraw the features
    })

  svg.call(zoom);
上述操作将允许用户通过鼠标平移或缩放与功能交互(通过投影)。D3.zoom跟踪累积缩放平移和缩放。我们将使用它来设置投影参数,然后使用更新的投影重新绘制所有功能,而不是使用它的值来设置SVG转换

但是,我们需要为缩放设置初始值。变焦的初始比例为1,对于d3.geoMercator投影,它将生成一个~6x6像素的世界。我们可以使用
选择设置初始缩放状态。调用(zoom.transform,transform)

平移表示视口的中心。对于D3墨卡托投影,比例通常是一个经度弧度所覆盖的像素数。墨卡托的默认中心为[0,0],因此上面的选项将使地图居中并将其缩放到视口

zoom.transform
触发缩放事件,重要的是更新缩放状态,以便投影和缩放对齐

最棘手的部分是使用
fitSize()
——这会修改投影,但不会修改缩放状态。但是,
fitSize()
只修改投影的平移和缩放,而不修改投影的中心。因此,我们可以简单地提取当前缩放和平移,并使用以下数据以编程方式触发缩放事件:

 function centerOnFeature(feature) {
    projection.fitSize([width,height],feature);
    var k = projection.scale();
    var t = projection.translate();
    svg.call(zoom.transform, d3.zoomIdentity.translate(...t).scale(k));
  }
请注意,这确实设置了两次投影参数:一次使用fitSize,一次使用zoom事件函数,这是可以避免的,但性能影响应该是不存在的,这是图形
 function centerOnFeature(feature) {
    projection.fitSize([width,height],feature);
    var k = projection.scale();
    var t = projection.translate();
    svg.call(zoom.transform, d3.zoomIdentity.translate(...t).scale(k));
  }