D3js画三维地球

  • 利用d3js在前端绘制三维地球并能够进行旋转
  • 代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<style>
body, html {
    font-family: arial;
}
.map {
    float: left;
    padding: 5px;
    border: solid 1px #eee;
    border-radius: 5px;
}
.graticule {
  fill: none;
  stroke: #777;
  stroke-width: .5px;
  stroke-opacity: .5;
  pointer-events: all;
}
.land {
  fill: none;
  stroke: #000;
  stroke-width: 1;
}
</style>
</head>

<body>
<div id="map" class="map"></div>
<script>

// https://stackoverflow.com/questions/43772975/drag-rotate-projection-in-d3-v4

  var width = 600,
      height = 600,
      scale = 200,
      origin = {
        x: 55,
        y: -40
      };
  var world;
// 选择body、div确定绘制地球位置和宽高
  var svg = d3.select('body').select('#map').append('svg')
    .attr('width', width)
    .attr('height', height);

  var group = svg.append("g").datum({
    x: 0,
    y: 0
  });
// 定义投影坐标系统
  var projection = d3.geoOrthographic()
    .scale(scale)
    .translate([width / 2, height / 2])
    .rotate([origin.x, origin.y])
    .center([0, 0])
    .clipAngle(90);
// 生成地理投影路径
  var geoPath = d3.geoPath()
    .projection(projection);
// 创建地球网格
  var graticule = d3.geoGraticule();

  // 地球缩放和拖拽
  svg.call(d3.zoom().on('zoom', zoomed));

  group.call(d3.drag().on('drag', dragged));

  // code snippet from http://stackoverflow.com/questions/36614251
  var lambda = d3.scaleLinear()
    .domain([-width, width])
    .range([-180, 180])

  var phi = d3.scaleLinear()
    .domain([-height, height])
    .range([90, -90]);
// 给地球添加网格并定义样式
  group.append('path')
    .datum(graticule)
    .attr('class', 'graticule')
    .attr('d', geoPath);

  function dragged(d) {
    var r = {
      x: lambda((d.x = d3.event.x)),
      y: phi((d.y = d3.event.y))
    };
    projection.rotate([origin.x + r.x, origin.y + r.y]);
    updatePaths(svg, graticule, world, geoPath);
  };

  function zoomed() {
    var transform = d3.event.transform;
    var k = Math.sqrt(100 / projection.scale());
    projection.scale(scale * transform.k)
    updatePaths(svg, graticule, world, geoPath);
  };

  function updatePaths(svg, graticule, world, geoPath) {
     svg.selectAll('path.graticule').datum(graticule).attr('d', geoPath);
     svg.selectAll('path.land').datum(world).attr('d', geoPath);
  };
// 加载全球json数据,绘制陆地
  d3.json("world-110m.json", function(error, worldJSON) {
     if (error) throw error;
     world = topojson.feature(worldJSON, worldJSON.objects.land);
     group.append("path")
      .datum(world)
      .attr("class", "land")
      .attr("d", geoPath);
  });

  var i=0;

  function redraw(){
      let proj = projection.rotate([0.2 * i, 0, 0]),
          path = d3.geoPath().projection(projection)

      group.selectAll("path")
          .datum(world)
          .attr("class", "land")
          .attr("d", geoPath);

      group.select("path")
          .datum(graticule)
          .attr("class", "graticule")
          .attr("d", geoPath);

      i ++

      window.requestAnimationFrame(redraw)
  }
// 调用地球重绘函数
//window.requestAnimationFrame(redraw)

</script>

</body>
</html>

效果看下面
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值