D3制作地球(三) —— Projection API

1,520 阅读3分钟

上文讲了如何得到各种各样的Projection,既然Projection是球体的经纬度在屏幕上的投影,那么我们也可以通过操作这个projection对象来控制投到屏幕上的地图,比如缩放、旋转、移动等等,D3提供了一系列的API操作projection对象,下面介绍一些常用API。

fit

当需要指定projection的offset和scale的时候,可以使用如下几个fit相关的API。

projection.fitExtent(extent, object)

这个API是指定投影面积的长宽和偏移量。参数extent的格式为[[x_0, y_0],[x_1, y_1]], 其中x_0投影左侧距离容器左边缘的距离,y_0是投影上侧距离容器上边缘的距离,x_1投影右侧距离容器左边缘的距离,y_0是投影下侧距离容器上边缘的距离。

假如用一个svg作为容器,大小是宽960px,高500px,想让投影距离容器的边框是20px,也就是padding是20px,那么参数extent应该指定为[[20, 20],[940, 480]]。

object参数指定的是你需要fit的那个对象,需要传入一个GeoJSON object,例如:

const projection = d3.geoOrthographic();
const sphere = {type: 'Sphere'};
projection.fitExtent([[20, 20],[940, 480]], sphere);

官方demo: bl.ocks.org/mbostock/51…

projection.fitSize(size, object)

这个API是projection.fitExtent(extent, object)的简写,当x_0y_0都是0的时候,可以用fitSize方法。

const projection = d3.geoOrthographic();
const sphere = {type: 'Sphere'};
projection.fitExtent([940, 480], sphere);

projection.fitWidth(width, object)

这个API是projection.fitSize(size, object)的简写,只需指定width,height根据图形的长宽比计算。 projection.fitHeight(height, object)同理。

rotate

rotate是指定projection旋转度的API。

projection.rotate([angles])

参数angles的格式是[lambda, phi, gamma]。为什么有三个元素呢?想象一个包含x轴,y轴,z轴的三维坐标系,一个球体的球心位于原点,球体以x轴为轴旋转的角度用phi表示,以y轴为轴旋转的角度用lambda表示,以z轴为轴旋转的角度用gamma表示,而lambda, phi, gamma三个变量就可以表示球体像这任意的方向旋转的角度。

官方demo:bl.ocks.org/mbostock/42…

事实上,不只是球体,空间中的任意物体的旋转角度,都可以用lambda, phi, gamma表示出来。更加形象的介绍可以参考: en.wikipedia.org/wiki/Aircra…

如果不传参数angles,则返回当前的旋转角度,projection的默认旋转角度是[0, 0, 0].

scale

scale指定projection的比例因子,比例因子描述两个投影点之间的距离。projection有默认的比例因子,前文描述了D3提供的很多种projection,每种projection的比例因子可能会不同。

projection.scale([scale])

参数scale是数值类型,如果不传参数则返回projection的当前scale的值。

translate

translate指定projection的中心距离容器左上角的位置。

projection.translate([translate])

参数translate的格式是[x, y], 如果参数设置为[0, 0],则projection的中心与容器左上角重合。

  const projection = d3.geoOrthographic();
  const sphere = { type: "Sphere" };
  const path = d3.geoPath().projection(projection);
  projection.translate([0, 0]);

  const svg = d3
    .select("body")
    .append("svg")
    .attr("style", 'border: 2px solid red')
    .attr("width", 960)
    .attr("height", 500);

  svg
    .insert("path")
    .datum(sphere)
    .attr("d", path)
    .attr("fill", "#3892dc");

translate的默认值是[480, 250],因此在不修改translate的情况下,当容器的大小是[960, 500]的时候,projection正好在容器的中央。

  const projection = d3.geoOrthographic();
  const sphere = { type: "Sphere" };
  const path = d3.geoPath().projection(projection);
  
  //不传参数会返回当前translate的值
  projection.translate(); //返回[480, 250]

  const svg = d3
    .select("body")
    .append("svg")
    .attr("style", 'border: 2px solid red')
    .attr("width", 960)
    .attr("height", 500);

  svg
    .insert("path")
    .datum(sphere)
    .attr("d", path)
    .attr("fill", "#3892dc");

center

指定将哪个经纬度作为projection的中心。

projection.center([center])

用法很简答,不赘述。默认值⟨0°,0°⟩。

项目在GitHub上的repo:github.com/dongqiaogon…

【完】