点击缩放后调整地图上的圆圈大小?

时间:2018-03-12 13:55:39

标签: javascript d3.js

D3的新手,所以我感谢您的耐心等待!我制作了一张地图,其中附加到城市坐标的圆圈的大小是.csv中的值。我还从Mike Bostock的一个例子中添加了点击缩放功能。

enter image description here

但是,放大时圈子不会调整大小。我不确定如何在放大和缩小时重新调整大小或重绘?

enter image description here

欢迎任何提示,示例或建议!这是我的代码:

<!DOCTYPE html>
<html>

<head>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <meta charset='utf-8'>
  <meta name="viewport" content='width=device-width, initial-scale=1.0'>
  <title></title>
  <style>
    .tooltip {
      line-height: 1;
      font-weight: bold;
      padding: 12px;
      background: rgba(0, 0, 0, 0.8);
      color: #fff;
      border-radius: 2px;
    }
  </style>
  <script>
    function draw(geo_data) {

      var margin = 20,
        width = 1500 - margin,
        height = 500 - margin;

      var centered;

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

      var formatComma = d3.format(",")

      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)
        .attr('fill', 'rgba(253, 227, 167, 0.8)')
        .attr('stroke', 'black')
        .attr('stroke-width', 0.4)
        .on('mouseover', function(d) {
          return d3.select(this).attr('fill', 'rgba(149, 165, 166, 0.8)')
        })
        .on('mouseout', function() {
          return d3.select(this).attr('fill', 'rgba(253, 227, 167, 0.8)')
        })
        // Why is this not working???
        .on('click', function() {
          return d3.select(this).attr('fill', 'rgba(149, 165, 166, 0.8)')
        })
        // Calls click-to-zoom function defined below.
        .on('click', clicked);

      var tooltip = svg.append('g')
        .attr('class', tooltip);

      tooltip.append('text')
        .attr('x', 15)
        .attr('class', 'tooltip')
        .attr('dy', '1.2em')
        .style('font-size', '1.5em')
        .attr('font-weight', 'bold');

      // Click-to-zoom function taken from Mike Bostock's code: https://bl.ocks.org/mbostock/2206590

      function clicked(d) {
        var x, y, k;

        if (d && centered !== d) {
          var centroid = path.centroid(d);
          x = centroid[0];
          y = centroid[1];
          k = 4;
          centered = d;
        } else {
          x = width / 2;
          y = height / 2;
          k = 1;
          centered = null;
        }

        map.selectAll('path')
          .classed('active', centered && function(d) {
            return d === centered;
          });

        map.transition()
          .duration(750)
          .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
          .style('stroke-width', 1 / k + 'px');
      }

      d3.csv('top100cities.csv', function(error, data) {

        // Converts strings in csv to integers so they can be used.

        data.forEach(function(d) {
          return d.guns = +d.guns;
        })

        // This returns the max number of guns.

        var guns = data.map(function(d) {
          return d.guns;
        });

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

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

        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);
          })
          .attr('fill', 'rgba(103, 65, 114, 0.5)')
          .attr('stroke', 'black')
          .on('mouseover', function(d) {
            return d3.select(this).attr('fill', 'rgba(103, 65, 114, 0.8)');
            tooltip.select('text').style('opacity', 1);
          })
          .on('mousemove', function(d) {
            var xPos = d3.mouse(this)[0] - 15;
            var yPos = d3.mouse(this)[1] - 55;
            tooltip.attr('transform', 'translate(' + xPos + ',' + yPos + ')');
            tooltip.select('text').style('opacity', 1);
            tooltip.select('text').text(d.city + ', ' + d.state + ': ' + formatComma(d.guns));
          })
          .on('mouseout', function(d) {
            tooltip.select('text').style('opacity', 0);
            return d3.select(this).attr('fill', 'rgba(103, 65, 114, 0.5)');
          });


      });
    };
  </script>
</head>

<body>
  <div id='map'></div>
  <script>
    d3.json('us_states.json', draw);
  </script>
</body>

1 个答案:

答案 0 :(得分:2)

您可以完成与地图完全相同的操作:

clicked功能中,在transformpath之后,您可以插入适用于circles的以下转换:

svg.selectAll('circle')
  .transition()
  .duration(750)
  .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
  .style('stroke-width', 1 / k + 'px');

&#13;
&#13;
<!DOCTYPE html>
<html>

<head>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <meta charset='utf-8'>
  <meta name="viewport" content='width=device-width, initial-scale=1.0'>
  <title></title>
  <style>
    .tooltip {
      line-height: 1;
      font-weight: bold;
      padding: 12px;
      background: rgba(0, 0, 0, 0.8);
      color: #fff;
      border-radius: 2px;
    }
  </style>
  <script>
    function draw(geo_data) {

      var margin = 20,
        width = 1500 - margin,
        height = 500 - margin;

      var centered;

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

      var formatComma = d3.format(",")

      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)
        .attr('fill', 'rgba(253, 227, 167, 0.8)')
        .attr('stroke', 'black')
        .attr('stroke-width', 0.4)
        .on('mouseover', function(d) {
          return d3.select(this).attr('fill', 'rgba(149, 165, 166, 0.8)')
        })
        .on('mouseout', function() {
          return d3.select(this).attr('fill', 'rgba(253, 227, 167, 0.8)')
        })
        // Why is this not working???
        .on('click', function() {
          return d3.select(this).attr('fill', 'rgba(149, 165, 166, 0.8)')
        })
        // Calls click-to-zoom function defined below.
        .on('click', clicked);

      var tooltip = svg.append('g')
        .attr('class', tooltip);

      tooltip.append('text')
        .attr('x', 15)
        .attr('class', 'tooltip')
        .attr('dy', '1.2em')
        .style('font-size', '1.5em')
        .attr('font-weight', 'bold');

      // Click-to-zoom function taken from Mike Bostock's code: https://bl.ocks.org/mbostock/2206590

      function clicked(d) {
        var x, y, k;

        if (d && centered !== d) {
          var centroid = path.centroid(d);
          x = centroid[0];
          y = centroid[1];
          k = 4;
          centered = d;
        } else {
          x = width / 2;
          y = height / 2;
          k = 1;
          centered = null;
        }

        map.selectAll('path')
          .classed('active', centered && function(d) {
            return d === centered;
          });

        map.transition()
          .duration(750)
          .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
          .style('stroke-width', 1 / k + 'px');

        svg.selectAll('circle')
          .transition()
          .duration(750)
          .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')scale(' + k + ')translate(' + -x + ',' + -y + ')')
          .style('stroke-width', 1 / k + 'px');
      }

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

        // Converts strings in csv to integers so they can be used.

        data.forEach(function(d) {
          return d.guns = +d.guns;
        })

        // This returns the max number of guns.

        var guns = data.map(function(d) {
          return d.guns;
        });

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

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

        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);
          })
          .attr('fill', 'rgba(103, 65, 114, 0.5)')
          .attr('stroke', 'black')
          .on('mouseover', function(d) {
            return d3.select(this).attr('fill', 'rgba(103, 65, 114, 0.8)');
            tooltip.select('text').style('opacity', 1);
          })
          .on('mousemove', function(d) {
            var xPos = d3.mouse(this)[0] - 15;
            var yPos = d3.mouse(this)[1] - 55;
            tooltip.attr('transform', 'translate(' + xPos + ',' + yPos + ')');
            tooltip.select('text').style('opacity', 1);
            tooltip.select('text').text(d.city + ', ' + d.state + ': ' + formatComma(d.guns));
          })
          .on('mouseout', function(d) {
            tooltip.select('text').style('opacity', 0);
            return d3.select(this).attr('fill', 'rgba(103, 65, 114, 0.5)');
          });


      });
    };
  </script>
</head>

<body>
  <div id='map'></div>
  <script>
    d3.json('https://raw.githubusercontent.com/dieterholger/US-Gun-Manufacturing-Interactive/master/us_states.json', draw);
  </script>
</body>
&#13;
&#13;
&#13;