d3.js React 中的可拖动地球仪实现

问题描述 投票:0回答:1

我是 d3.js 的新手,对使用 svgs 的经验很少。我无法使地球仪在拖动时水平和垂直旋转。旋转仅在水平方向上起作用,并且作用在整个 svg 而不仅仅是地球上。这是我的代码:

import * as d3 from "d3";
import { geoOrthographic, geoPath } from "d3-geo";
import { useEffect, useRef, useState } from "react";
import { feature } from "topojson-client";

export default function Globe() {
  const [geographies, setGeographies] = useState([]);
  const [width, setWidth] = useState(0);
  const [height, setHeight] = useState(0);
  const svgRef = useRef();

  useEffect(() => {
    d3.json("/data/world-data.json").then((worldData) => {
      const mapFeature = feature(worldData, worldData.objects.countries).features;
      setGeographies(mapFeature);
    });

    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  }, []);

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

    const projection = geoOrthographic()
      .scale(280)
      .translate([width / 2, height / 2])
      .center([0, 0])
      .rotate([0, -25]);

    const path = geoPath(projection);

    svg
      .selectAll("path")
      .data(geographies)
      .enter()
      .append("path")
      .attr("d", (d) => path(d))
      .attr("fill", "rgba(255,255,255,.5)")
      .attr("stroke", "white")
      .attr("stroke-width", 0.5);

    svg.call(
      d3.drag().on("drag", (event) => {
        const [x, y] = d3.pointer(event);
        const rotate = projection.rotate();
        const k = 5 / projection.scale();
        projection.rotate([rotate[0] + k * (x - width / 2), rotate[1]]);
        svg.selectAll("path").attr("d", (d) => path(d));
      })
    );
  }, [geographies, height, width]);

  return (
    <svg ref={svgRef} width={width} height={height} viewBox={`0 0 ${width} ${height}`}>
    </svg>
  );
}

我想修复地球仪的交互,并且能够通过拖动水平和垂直旋转地球仪。我尝试更改projection.rotate() 上的y,但它没有按预期工作。有人可以帮我吗?

我尝试更改projection.rotation()中的y值,但与地球仪的交互无法正常工作。我也尝试检查示例,但没有找到任何可以帮助我的东西。

d3.js react-d3
1个回答
0
投票

错误出现在projection.rotate()参数上。这是我的解决方案:

svg.call(
  d3.drag().on("drag", (event) => {
    const rotate = projection.rotate();
    const k = 75 / projection.scale();
    projection.rotate([rotate[0] + event.dx * k, rotate[1] - event.dy * k]);
    svg.selectAll("path").attr("d", (d) => path(d));
  })
);
© www.soinside.com 2019 - 2024. All rights reserved.