Kulwant
Kulwant

Reputation: 681

D3 Bar Chart - Reverse Bars from Right to Left

I am new to D3. I am working through a current example. What I am trying to do is reverse the bar chart, so all labels start at the end of the graph. I changed the x-coordinate to width, instead of 0 and also tried to change the width to a negative width.

Here is my current version.

I basically want all of the bars to start at the 100 mark, not at 0. Thanks!

https://plnkr.co/edit/fqW0i3H3ZACJx1oeViR6?p=preview

var svg = d3.select("svg"),
  margin = { top: 20, right: 20, bottom: 30, left: 80 },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom;

var tooltip = d3
  .select("body")
  .append("div")
  .attr("class", "toolTip");

var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleBand().range([height, 0]);

var g = svg
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

d3.json("data.json", function(error, data) {
  if (error) throw error;

  data.sort(function(a, b) {
    return a.value - b.value;
  });

  x.domain([
    0,
    d3.max(data, function(d) {
      return d.value;
    })
  ]);
  y.domain(
    data.map(function(d) {
      return d.area;
    })
  ).padding(0.1);

  g.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(
      d3
        .axisBottom(x)
        .ticks(5)
        .tickFormat(function(d) {
          return parseInt(d / 1000);
        })
        .tickSizeInner([-height])
    );

  g.append("g")
    .attr("class", "y axis")
    .call(d3.axisLeft(y));

  g.selectAll(".bar")
    .data(data)
    .enter()
    .append("rect")
    .attr("class", "bar")
    .attr("x", 0)
    .attr("height", y.bandwidth())
    .attr("y", function(d) {
      return y(d.area);
    })
    .attr("width", function(d) {
      return x(d.value);
    })
    .on("mousemove", function(d) {
      tooltip
        .style("left", d3.event.pageX - 50 + "px")
        .style("top", d3.event.pageY - 70 + "px")
        .style("display", "inline-block")
        .html(d.area + "<br>" + "£" + d.value);
    })
    .on("mouseout", function(d) {
      tooltip.style(
        "display",

        "none"
      );
    });
});

The original example is here:

https://bl.ocks.org/alandunning/7008d0332cc28a826b37b3cf6e7bd998

I look at a previous answer and thought to change the x-attribute on the rect from .attr("x",0) to .attr("x", function(d){return width-x(d.value)}) but that didn't work either.

Upvotes: 2

Views: 5078

Answers (2)

ofey
ofey

Reputation: 3327

First reverse the domain,

x.domain([d3.max(data, function(d) { return d.value; }),0]);

Set the bars to start at,

 .attr("x", function(d){return x(d.value)})

and the width,

   .attr("width", function(d) { return width - x(d.value); })

enter image description here

Upvotes: 2

Mark
Mark

Reputation: 92440

I'm assuming you want to reverse the axis as well. To do this and have the bars go from right to left, you need to change both the range and how you draw the rects.

The range should look like this to get the axis correct:

var x = d3.scaleLinear().range([width, 0]);

Then you can draw the rects like this to put them in the correct spot:

.attr("x", function(d){return x(d.value) })
.attr("width", function(d) { return x(0) - x(d.value); })

Here's a fiddle: https://plnkr.co/edit/4YLPCQ4SE35l4vZUy2tF?p=preview

Is that what you meant?

Upvotes: 4

Related Questions