0

I am trying to take the D3 Hexbin example found at https://bl.ocks.org/mbostock/4330486 and scale the map to fit the width of the parent element. I have followed the code found in the answer Center a map in d3 given a geoJSON object, but the map is all messed up (see code snippet below). The goal of this change is to allow the map to be on a responsive webpage.

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

var parseDate = d3.timeParse("%x");

var color = d3.scaleTime()
    .domain([new Date(1962, 0, 1), new Date(2006, 0, 1)])
    .range(["black", "steelblue"])
    .interpolate(d3.interpolateLab);

var hexbin = d3.hexbin()
    .extent([[0, 0], [width, height]])
    .radius(10);

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

// Per https://github.com/topojson/us-atlas
var projection = d3.geoAlbersUsa()
    .scale(1)
    .translate([0, 0]);

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

d3.queue()
    .defer(d3.json, "https://d3js.org/us-10m.v1.json")
    .await(ready);

function ready(error, us, walmarts) {
  if (error) throw error;

 var country = topojson.feature(us, us.objects.nation);
  
  var b = path.bounds(country),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
    t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
 projection
    .scale(s)
    .translate(t);
    
  svg.append("path")
      .datum(country)
      .attr("class", "nation")
      .attr("d", path);

  svg.append("path")
      .datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
      .attr("class", "states")
      .attr("d", path);

}
.nation {
  fill: #ddd;
}

.states {
  fill: none;
  stroke: #fff;
  stroke-linejoin: round;
}

.hexagon {
  stroke: #fff;
}
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
Brant Olsen
  • 5,628
  • 5
  • 36
  • 53

1 Answers1

1

You can make your d3js chart responsive by using viewBox. To make a d3js chart responsive, you have to remove width and height and use viewBox.

The changes is simple just use <svg></svg> instead of <svg width="960" height="600"></svg> And then just add the viewBox attribute on the svg like below:

var width = 960,
height = 600,
svg = d3.select("svg");

svg.attr("viewBox", "0 0 " + width + " " + height);

Please check running example snippet:

var width = 960,
  height = 600,
  svg = d3.select("svg");

svg.attr("viewBox", "0 0 " + width + " " + height);

var parseDate = d3.timeParse("%x");

var color = d3.scaleTime()
  .domain([new Date(1962, 0, 1), new Date(2006, 0, 1)])
  .range(["black", "steelblue"])
  .interpolate(d3.interpolateLab);

var hexbin = d3.hexbin()
  .extent([
    [0, 0],
    [width, height]
  ])
  .radius(10);

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

// Per https://github.com/topojson/us-atlas
var projection = d3.geoAlbersUsa()
  .scale(1280)
  .translate([480, 300]);

var path = d3.geoPath();

d3.queue()
  .defer(d3.json, "https://d3js.org/us-10m.v1.json")
  .await(ready);

function ready(error, us, walmarts) {
  if (error) throw error;

  var country = topojson.feature(us, us.objects.nation);

  var b = path.bounds(country),
    s = .95 / Math.max((b[1][0] - b[0][0]) / width, (b[1][1] - b[0][1]) / height),
    t = [(width - s * (b[1][0] + b[0][0])) / 2, (height - s * (b[1][1] + b[0][1])) / 2];
  projection
    .scale(s)
    .translate(t);

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

  svg.append("path")
    .datum(topojson.mesh(us, us.objects.states, function(a, b) {
      return a !== b;
    }))
    .attr("class", "states")
    .attr("d", path);

}
.nation {
  fill: #ddd;
}

.states {
  fill: none;
  stroke: #fff;
  stroke-linejoin: round;
}

.hexagon {
  stroke: #fff;
}
<div style="height: 100px; width: 100px;">
  <svg></svg>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-hexbin.v0.2.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
Brant Olsen
  • 5,628
  • 5
  • 36
  • 53
csharpbd
  • 3,786
  • 4
  • 23
  • 32