D3.js学习笔记:绘制等值线图

目录

D3.js的5.X版本新增d3-contour组件,支持绘制等值线图。本文介绍使用d3-contour绘制气象要素等值线图的方法。

数据

使用等经纬度网格的气象要素场,使用《GRIB2要素场转换为图片》介绍的方法,通过图片加载数据。

使用fetch加载图片和描述文件,使用jimp获取图片像素值。

Promise.all([
  Jimp.read("public/data/t.png"),
  fetch("public/data/t.json"),
]).then(values => {
  let data_image = values[0];
  let metadata_response = values[1];
  metadata_response.json().then(metadata => {
    let values = data_image.bitmap.data.filter((value: number, index: number) => {
      return (index % 4) == 0
    });

    let real_values = _.map(values, value => {
      return (metadata.max_value-metadata.min_value) * value / 255 + metadata.min_value;
    });

    // continue to draw contours
  });
});

上述代码使用描述文件中的信息将图像灰度值数组values恢复为数据实际值数组real_values

绘制等值线填充图

在svg上绘制等值线,创建svg节点,指定宽度和高度。

let width = 1600.;
let height = 800.;

let svg = d3.select("#page")
  .append("svg")
  .style("width", width)
  .style("height", height);

使用d3.ticks构建等值线的间隔,并为每个间隔分配一个颜色。这里我将最大值最小值区间等分为20分,使用d3.interpolateMagma色表。

let thresholds = d3.ticks(metadata.min_value, metadata.max_value, 20);

let color = d3.scaleSequential(d3.interpolateMagma)
    .domain(d3.extent(thresholds));

使用d3.contours构建等值线,设置数据矩阵的行宽和列宽,设置等值线间隔,使用实际的数据值生成等值线对象。返回的结果是GeoJSON的数组,每个元素代表一个间隔的等值线。

let contours = d3.contours()
    .size([metadata.nx, metadata.ny])
    .thresholds(thresholds)
    (real_values);

使用d3.geoPath绘制等值线。这里我将每层的颜色赋值给pathfill属性,用于绘制填充图。

let contour_g = svg.append('g');
contour_g.selectAll(".contour")
    .data(contours)
    .enter().append("path")
    .attr("class", "contour")
    .attr("d", d3.geoPath())
    .attr("fill", function(d) { return color(d.value); });

显示效果如下图所示

绘制等值线

将层次的颜色赋值给pathstroke属性,就可以绘制等值线。

contour_g.selectAll(".contour")
  .data(contours)
  .enter().append("path")
  .attr("class", "contour")
  .attr("d", d3.geoPath())
  .attr("stroke", function(d) { return color(d.value); })
  .attr("fill", "none");

效果如下图所示

参考

d3-contour

jimp