使用Math.sqrt()而不是d3.scaleSqrt()来调整地图上的圆圈大小?

时间:2018-03-10 05:15:28

标签: d3.js

我正在制作一张地图,其中附加到美国地图上城市的圆圈的大小取决于CSV中的值(guns列或JavaScript中的d.guns)。

我可以在添加圈子的同时使用Math.sqrt()让圈子调整大小,但我不认为这是正确的方法(或者它没问题?):

.attr('r', function(d) {
  return Math.sqrt(d.guns * 0.0010);
})

Here's how the map looks right now.

我尝试使用d3.scaleSqrt()d3.extent根据值调整圈子的大小,但是我在控制台中抛出了这些错误:

Console errors

以下是我尝试使用d3.scaleSqrt时的代码:

<head>
  <script>
    function draw(geo_data) {
      'use strict';

      var margin = 75,
        width = 1920 - margin,
        height = 1080 - margin;

      var svg = d3.select('body')
        .append('svg')
        .attr('width', width + margin)
        .attr('height', height + margin)
        .append('g')
        .attr('class', 'map');

      var projection = d3.geoAlbersUsa();

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

      var map = svg.selectAll('path')
        .data(geo_data.features)
        .enter()
        .append('path')
        .attr('d', path)
        .style('fill', 'rgba(253, 227, 167, 0.8)')
        .style('stroke', 'black')
        .style('stroke-width', 0.4);

      d3.csv('top100cities.csv', function(error, data) {
    // Converts strings to integers.

    data.forEach(function(d) {
      return d.guns = +d.guns;
    })
        var guns_extent = d3.extent(function(d) {
          return d.guns;
        });

        var radius = d3.scaleSqrt()
          .domain(guns_extent)
          .range([0, 12]);

        svg.append('g')
          .attr('class', 'bubble')
          .selectAll('circle')
          .data(data)
          .enter()
          .append('circle')
          .attr('cx', function(d) {
            return projection([d.lon, d.lat])[0];
          })
          .attr('cy', function(d) {
            return projection([d.lon, d.lat])[1];
          })
          .attr('r', function(d) {
            return radius(d.guns);
          })
          .style('fill', 'rgba(103, 65, 114, 0.5)');

      });

    };
</script>

<body>
<script>
d3.json('us_states.json', draw);
</script>
</body>

3 个答案:

答案 0 :(得分:4)

虽然Xavier Guihot的answer在技术上是正确的并提出了一个有效的解决方案,但它略微偏离了D3赛道。您的代码中的错误是由于未向d3.extent()提供所有参数而导致的。你只是忘了传入数组,即data,从中确定范围(强调我的):

  

# d3.extent( array [, accessor ])<>

     

使用自然顺序返回给定 数组 中的minimummaximum值。同时提供数组和访问器,您的代码将如下所示:

var guns_extent = d3.extent(data, function(d) {   // Pass in data as first parameter
  return d.guns;
});

以下是工作演示:

function draw(geo_data) {
  'use strict';

  var margin = 75,
    width = 1920 - margin,
    height = 1080 - margin;

  var svg = d3.select('body')
    .append('svg')
    .attr('width', width + margin)
    .attr('height', height + margin)
    .append('g')
    .attr('class', 'map');

  var projection = d3.geoAlbersUsa();

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

  var map = svg.selectAll('path')
    .data(geo_data.features)
    .enter()
    .append('path')
    .attr('d', path)
    .style('fill', 'rgba(253, 227, 167, 0.8)')
    .style('stroke', 'black')
    .style('stroke-width', 0.4);

  d3.csv("https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv", function(error, data) {
    // Converts strings to integers.

    data.forEach(function(d) {
      return d.guns = +d.guns;
    })
    var guns_extent = d3.extent(data, function(d) {   // Pass in data
      return d.guns;
    });

    var radius = d3.scaleSqrt()
      .domain(guns_extent)
      .range([0, 12]);

    svg.append('g')
      .attr('class', 'bubble')
      .selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('cx', function(d) {
        return projection([d.lon, d.lat])[0];
      })
      .attr('cy', function(d) {
        return projection([d.lon, d.lat])[1];
      })
      .attr('r', function(d) {
        return radius(d.guns);
      })
      .style('fill', 'rgba(103, 65, 114, 0.5)');

  });

};

d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
<script src="https://d3js.org/d3.v4.js"></script>

答案 1 :(得分:3)

我认为错误在于检索枪支的最大数量。

这是差异:

let guns = data.map( function(d) { return d.guns });
console.log(Math.max(...guns));

var radius = d3.scaleSqrt().domain([0, Math.max(...guns)]).range([0, 25]);

以下是经过修改的演示:

<head>
  <script>
    function draw(geo_data) {
      'use strict';

      var margin = 75,
        width = 1920 - margin,
        height = 1080 - margin;

      var svg = d3.select('body')
        .append('svg')
        .attr('width', width + margin)
        .attr('height', height + margin)
        .append('g')
        .attr('class', 'map');

      var projection = d3.geoAlbersUsa();

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

      var map = svg.selectAll('path')
        .data(geo_data.features)
        .enter()
        .append('path')
        .attr('d', path)
        .style('fill', 'rgba(253, 227, 167, 0.8)')
        .style('stroke', 'black')
        .style('stroke-width', 0.4);

  d3.csv('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/top100cities.csv', function(error, data) {

    let guns = data.map( function(d) { return d.guns });
    console.log(Math.max(...guns));

    var radius = d3.scaleSqrt().domain([0, Math.max(...guns)]).range([0, 25]);

    svg.append('g')
      .attr('class', 'bubble')
      .selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('cx', function(d) {
        return projection([d.lon, d.lat])[0];
      })
      .attr('cy', function(d) {
        return projection([d.lon, d.lat])[1];
      })
      .attr('r', function(d) {
        return radius(d.guns);
      })
      .style('fill', 'rgba(103, 65, 114, 0.5)');

      });

    };
</script>

<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
</script>
</body>

答案 2 :(得分:0)

设置圆形区域的公式可能会起作用。

公式为A=πr2,其中A等于圆的面积,r等于半径。

如果A = d.guns

我们知道Areaπ

然后:

r = √(d.guns/π)

.attr("r", function (d) {return Math.sqrt(d.guns/3.1416);})

https://www.wikihow.com/Calculate-the-Radius-of-a-Circle#/Image:Calculate-the-Radius-of-a-Circle-Step-10-Version-4.jpg