Om Sao
Om Sao

Reputation: 7683

D3 Data Visualisation aligning tick labels and rect

I am new to D3 library for Data Visualisation. I am trying to create a vertical legend. And below is my implementation. We can see there is huge gap between the column of rects(are on extreme right) and vertical ticks.

I guess, I am missing something in g.call because of my limited knowledge.

Can someone please, what mistake I am doing ?

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>

.counties {
  fill: none;
}

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

</style>
<svg width="1260" height="600"></svg>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
</head>
<body>
<script>

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

var poverty = d3.map();

var path = d3.geoPath();

var x = d3.scaleLinear()
    //.domain([1, 10])
	.domain([1, 10])
    .rangeRound([600, 860]);
//console.log("x:==>", x);

var y = d3.scaleLinear()
    //.domain([1, 10])
	.domain([1, 10])
    .rangeRound([15, 160]);
	
var color = d3.scaleThreshold()
    //.domain(d3.range(2, 10))
	.domain(d3.range(2, 10))
    .range(d3.schemeBlues[9]);

var g = svg.append("g")
    .attr("class", "key")
	//.attr("transform", "translate(0,40)");
    .attr("transform", "translate(350,40)");

g.selectAll("rect")
  .data(color.range().map(function(d) {
      d = color.invertExtent(d);
      if (d[0] == null) d[0] = x.domain()[0];
      if (d[1] == null) d[1] = x.domain()[1];
      return d;
    }))
  .enter().append("rect")
    /*.attr("height", 8)
    .attr("x", function(d) { return x(d[0]); })
    .attr("width", function(d) { return x(d[1]) - x(d[0]); })
    .attr("fill", function(d) { return color(d[0]); })*/
	 .attr("height", 15)
    .attr("x", 600)
	.attr("y", function(d) { return y(d[0]); })
    .attr("width", function(d) { return x(d[1]) - x(d[0]); })
    .attr("fill", function(d) { return color(d[0]); })	;

g.append("text")
    .attr("class", "caption")
    /*.attr("x", x.range()[0])
    .attr("y", -6)*/
	.attr("x",x.range()[0])
    .attr("y", -6)
    .attr("fill", "#000")
    .attr("text-anchor", "start")
    .attr("font-weight", "bold")
    .text("Poverty rate");

g.call(d3.axisRight(y)
    //.tickSize(13)
    .tickFormat(function(x, i) { return i ? 2*x : 2*x + "%"; })
    .tickValues(color.domain()))

  .select(".domain")
    .remove();

var promises = [

  d3.json("https://snippetnuggets.com/TnD/us.json"),
  d3.csv("https://snippetnuggets.com/TnD/county_poverty.csv", function(d) { poverty.set(d.id, +d.rate); console.log(d); })
]

Promise.all(promises).then(ready)

function ready([us]) {
  svg.append("g")
      .attr("class", "counties")
    .selectAll("path")
    .data(topojson.feature(us, us.objects.counties).features)
    .enter().append("path")
      .attr("fill", function(d) { return color(d.rate = poverty.get(d.id)); })
      .attr("d", path)
    .append("title")
      .text(function(d) { return d.rate + "%"; });

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


</script>
</body>
</html>

Upvotes: 1

Views: 247

Answers (1)

matthias.rocks
matthias.rocks

Reputation: 625

Your large gap between your axis ticks/labels and legend rects is there because you set x to 600 on your rects (.attr("x", 600)), which means you position the rects 600 pixels to the right, relative to the rects' parent container.

What happens is that first you append a g element, which you translate 350 pixels horizontally to the right (and 40 vertically downwards). When you later append rects to this g element, the rects are positioned relative to the g elements position. Therefore, setting the x attribute on the rects to 600 means in effect that you position the rects 950 pixels (350 + 600) to the right of the left side of the SVG.

To fix this, you should lower your x attribute on the rects. Negative values are valid too.

Check the reference for SVG rect elements here: SVG

Upvotes: 2

Related Questions