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