首页 > 编程知识 正文

绘制地球五带示意图

时间:2023-11-20 09:20:57 阅读:293998 作者:FTDW

本文将从以下方面为大家讲解如何绘制地球五带示意图:

一、绘图工具的选择

在绘制地球五带示意图之前,我们需要选择一款好用的绘图工具。推荐使用D3.js库,它是一个非常有名的JavaScript可视化库,可以方便地完成复杂的数据可视化任务,其中包括地图可视化。你可以在以下的代码示例中看到如何使用D3.js绘制简单的地球五带示意图:

<html>
  <head>
    <script src="https://d3js.org/d3.v5.min.js"></script>
  </head>
  <body>
    <svg width="960" height="480"></svg>
    <script>
      var svg = d3.select("svg");

      var projection = d3.geoOrthographic();
      var path = d3.geoPath(projection);

      var graticule = d3.geoGraticule();

      svg.append("defs").append("path")
          .datum({type: "Sphere"})
          .attr("id", "sphere")
          .attr("d", path);

      svg.append("use")
          .attr("class", "fill")
          .attr("xlink:href", "#sphere");

      svg.append("path")
          .datum(graticule)
          .attr("class", "graticule")
          .attr("d", path);
    </script>
  </body>
</html>

二、绘制地球五带

为了让地球五带更加直观,我们需要在地球上标出五个带状区域,即热带、亚热带、温带、寒带和极地带。下面的代码示例展示了如何在地球上绘制五个带状区域:

var svg = d3.select("svg");

var projection = d3.geoOrthographic();
var path = d3.geoPath(projection);

var graticule = d3.geoGraticule();


svg.append("defs").append("path")
    .datum({type: "Sphere"})
    .attr("id", "sphere")
    .attr("d", path);

svg.append("use")
    .attr("class", "fill")
    .attr("xlink:href", "#sphere");

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

svg.append("path")
    .datum({type: "Sphere"})
    .attr("class", "stroke")
    .attr("d", path);

svg.append("path")
    .datum({type: "Sphere"})
    .attr("class", "fill")
    .attr("d", path);

var bands = [
  {from: 23.5, to: -23.5, name: "热带"},
  {from: 66.5, to: 23.5, name: "亚热带"},
  {from: 90, to: 66.5, name: "温带"},
  {from: -66.5, to: -90, name: "寒带"},
  {from: -23.5, to: -66.5, name: "极地带"}
];

var bandPaths = [];

for (var i = 0; i < bands.length; i++) {
  var band = bands[i];

  var fromLat = band.from;
  var toLat = band.to;
  var fromLng = -180;
  var toLng = 180;

  var bandPolygon = [
    [fromLng, fromLat],
    [toLng, fromLat],
    [toLng, toLat],
    [fromLng, toLat],
    [fromLng, fromLat]
  ];

  var geoJSON = {type: 'Polygon', coordinates: [bandPolygon]};

  var bandPath = svg.append("path")
      .datum(geoJSON)
      .attr("class", "band-" + (i+1))
      .attr("d", path);

  bandPaths.push(bandPath);

  svg.append("text")
      .attr("class", "band-label")
      .attr("text-anchor", "middle")
      .attr("dy", -10)
      .append("textPath")
      .attr("xlink:href", "#band-path-" + (i+1))
      .attr("startOffset", "50%")
      .text(band.name);
}

三、调整地球视角

为了让地球五带示意图更加清晰,我们需要调整地球的视角,比如增加旋转效果、使五带更加突出等。下面的代码示例演示了如何使地球旋转,以及如何使热带区域更加突出:

var svg = d3.select("svg");

var width = +svg.attr("width"),
    height = +svg.attr("height");

var projection = d3.geoOrthographic()
    .scale(240)
    .translate([width / 2, height / 2])
    .rotate([-30, -20]);

var path = d3.geoPath()
    .projection(projection);

var graticule = d3.geoGraticule();

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

var sphere = svg.append("path")
    .datum({type: "Sphere"})
    .attr("class", "sphere")
    .attr("d", path);

d3.timer(function(elapsed) {
  projection.rotate([-elapsed * 0.1, -20])
  sphere.attr("d", path)
})

var bands = [
  {from: 23.5, to: -23.5, name: "热带"},
  {from: 66.5, to: 23.5, name: "亚热带"},
  {from: 90, to: 66.5, name: "温带"},
  {from: -66.5, to: -90, name: "寒带"},
  {from: -23.5, to: -66.5, name: "极地带"}
];

var bandPaths = [];

for (var i = 0; i < bands.length; i++) {
  var band = bands[i];

  var fromLat = band.from;
  var toLat = band.to;
  var fromLng = -180;
  var toLng = 180;

  var bandPolygon = [
    [fromLng, fromLat],
    [toLng, fromLat],
    [toLng, toLat],
    [fromLng, toLat],
    [fromLng, fromLat]
  ];

  var geoJSON = {type: 'Polygon', coordinates: [bandPolygon]};

  var bandPath = svg.append("path")
      .datum(geoJSON)
      .attr("class", "band")
      .attr("d", path);

  bandPaths.push(bandPath);
}

var tropicalBands = [
  bandPaths[0]
];

svg.append("rect")
    .attr("class", "tropical-highlight")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", width)
    .attr("height", height)
    .attr("opacity", 1e-6)
    .on("mouseover", function() {
      d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 0.7);
      tropicalBands.forEach(function(band) {
        band.transition()
            .duration(300)
            .attr("stroke-width", "3")
            .attr("stroke", "red");
      });
    })
    .on("mouseout", function() {
      d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 1e-6);
      tropicalBands.forEach(function(band) {
        band.transition()
            .duration(300)
            .attr("stroke-width", "1")
            .attr("stroke", "black");
      });
    });

四、添加交互功能

为了使地球五带示意图更加生动,我们可以为其添加交互功能,比如当用户悬停在某个带状区域时,该区域会被突出显示;当用户单击某个带状区域时,地图会自动调整到该区域的视角等。下面的代码示例展示了如何为地球五带示意图添加悬停和单击交互功能:

var svg = d3.select("svg");

var width = +svg.attr("width"),
    height = +svg.attr("height");

var projection = d3.geoOrthographic()
    .scale(240)
    .translate([width / 2, height / 2])
    .rotate([-30, -20]);

var path = d3.geoPath()
    .projection(projection);

var graticule = d3.geoGraticule();

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

var sphere = svg.append("path")
    .datum({type: "Sphere"})
    .attr("class", "sphere")
    .attr("d", path);

d3.timer(function(elapsed) {
  projection.rotate([-elapsed * 0.1, -20])
  sphere.attr("d", path)
})

var bands = [
  {from: 23.5, to: -23.5, name: "热带", color: "#FF4040"},
  {from: 66.5, to: 23.5, name: "亚热带", color: "#FFA500"},
  {from: 90, to: 66.5, name: "温带", color: "#FFFF00"},
  {from: -66.5, to: -90, name: "寒带", color: "#1E90FF"},
  {from: -23.5, to: -66.5, name: "极地带", color: "#00FA9A"}
];

var bandPaths = [];

for (var i = 0; i < bands.length; i++) {
  var band = bands[i];

  var fromLat = band.from;
  var toLat = band.to;
  var fromLng = -180;
  var toLng = 180;

  var bandPolygon = [
    [fromLng, fromLat],
    [toLng, fromLat],
    [toLng, toLat],
    [fromLng, toLat],
    [fromLng, fromLat]
  ];

  var geoJSON = {type: 'Polygon', coordinates: [bandPolygon]};

  var bandPath = svg.append("path")
      .datum(geoJSON)
      .attr("class", "band")
      .attr("d", path)
      .attr("fill", band.color)
      .attr("stroke", "black")
      .attr("stroke-width", "1")
      .on("mouseover", function(d) {
        d3.select(this)
            .attr("stroke-width", "3")
            .attr("stroke", "red");
      })
      .on("mouseout", function(d) {
        d3.select(this)
            .attr("stroke-width", "1")
            .attr("stroke", "black");
      })
      .on("click", function(d) {
        var centroid = path.centroid(d);
        var rotate = projection.rotate();
        projection.rotate([-centroid[0], -centroid[1], -rotate[2]]);
        svg.selectAll(".band")
            .transition()
            .duration(1000)
            .attrTween("d", function (d) { return function(t) { return path(d); }; });
      });

  bandPaths.push(bandPath);
}

var tropicalBands = [
  bandPaths[0]
];

svg.append("rect")
    .attr("class", "tropical-highlight")
    .attr("x", 0)
    .attr("y", 0)
    .attr("width", width)
    .attr("height", height)
    .attr("opacity", 1e-6)
    .on("mouseover", function() {
      d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 0.7);
      tropicalBands.forEach(function(band) {
        band.transition()
            .duration(300)
            .attr("stroke-width", "3")
            .attr("stroke", "red");
      });
    })
    .on("mouseout", function() {
      d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 1e-6);
      tropicalBands.forEach(function(band) {
        band.transition()
            .duration(300)
            .attr("stroke-width", "1")
            .attr("stroke", "black");
      });
    });

五、结语

通过本篇文章的讲解,你现在已经知道如何使用D3.js库绘制地球五带示意图了。但是,本篇文章仅仅介绍了其中的基础部

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。