score:1

Accepted answer

Here's a couple examples I just put together. The first is the straight d3 way of doing what you are asking. The second is a hacked up plottable.js. With plottable.js I can't find a way to position the axis outside of their table system, I had to resort to manually moving them. The table system they use is designed to relieve the developer of having to manually position things. This is great and easy, of course, until you want to control where to position things.

Here's the hack, after you render your plottable:

  // move the axis...
  d3.select(".y-axis")
    .attr('transform',"translate(" + width / 2 + "," + 0 + ")");        
  d3.select(".x-axis")
    .attr("transform", "translate(" + 48 + "," + height / 2 + ")");

Note, I didn't remove the left side margin (the 48 above) that plottable puts in. This could be hacked in as well, but at that point, what is plottable providing for you anyway...

It should be noted that the different appearance of each plot is entirely controlled through the CSS.

Complete d3 scatter plot:

// D3 EXAMPLE
var margin = {
  top: 20,
  right: 20,
  bottom: 20,
  left: 20
},
  width = 500 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

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

var y = d3.scale.linear()
  .range([height, 0]);

var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom");

var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left");

var svg = d3.select("#d3").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

x.domain([-100, 100]);
y.domain([-100, 100]);

svg.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(" + 0 + "," + height / 2 + ")")
  .call(xAxis);

svg.append("g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + width / 2 + "," + 0 + ")")
  .call(yAxis)
  .append("text");

svg.selectAll(".dot")
  .data(data)
  .enter().append("circle")
  .attr("class", "dot")
  .attr("r", function(d) {
    return d.r;
  })
  .attr("cx", function(d) {
    return x(d.x);
  })
  .attr("cy", function(d) {
    return y(d.y);
  })
  .style("fill", function(d) {
    return d.c;
  });

enter image description here

Plottable.js:

  // PLOTTABLE.JS
  var xScale = new Plottable.Scale.Linear();
  var yScale = new Plottable.Scale.Linear();

  var xAxis = new Plottable.Axis.Numeric(xScale, "bottom");
  var yAxis = new Plottable.Axis.Numeric(yScale, "left");

  var plot = new Plottable.Plot.Scatter(xScale, yScale);
  plot.addDataset(data);

  function getXDataValue(d) {
    return d.x;
  }
  plot.project("x", getXDataValue, xScale);
  function getYDataValue(d) {
    return d.y;
  }
  plot.project("y", getYDataValue, yScale);
  function getRDataValue(d){
    return d.r;
  }
  plot.project("r", getRDataValue);
  function getFillValue(d){
    return d.c;
  }
  plot.project("fill", getFillValue);
  var chart = new Plottable.Component.Table([
                    [yAxis, plot],
                    [null,  xAxis]
                  ]);
  chart.renderTo("#plottable");

  d3.select(".y-axis")
    .attr('transform',"translate(" + width / 2 + "," + 0 + ")");

  d3.select(".x-axis")
    .attr("transform", "translate(" + 48 + "," + height / 2 + ")");

enter image description here

score:2

Mark has the right idea - the table system doesn't natively support this layout, so you need to take some manual control over how they are laid out. However, using somewhat obscure parts of the Plottable API, there is a cleaner and better-supported way to lay out the chart you want, which doesn't have the problem of the axes being slightly offset.

The first change is we are going to stop using the table layout engine entirely, since it isn't able to do what we want. Instead, we will plop all the components together in a Component.Group. A Group just overlays components in the same space without trying to position them at all.

var chart = new Plottable.Component.Group([yAxis, xAxis, plot]);

Then we are going to use the alignment and offset methods that are defined on the base (abstract) component class. We set the x-alignment of the y axis to "center" and the y-alignment of the x axis to "center" This will put the axes in the center of the chart.

var xAxis = new Plottable.Axis.Numeric(xScale, "bottom").yAlign("center"); var yAxis = new Plottable.Axis.Numeric(yScale, "left").xAlign("center");

We're not quite done at this point, since to really center the axes we need to shift them back by one half of their own width. The width is only calculated when the chart is rendered (strictly speaking, in the computeLayout call, but that is an internal detail), so we need to set an offset after the chart is rendered:

chart.renderTo("#plottable"); xAxis.yOffset(xAxis.height()/2); yAxis.xOffset(-yAxis.width()/2);

You can see the final result here (it's a fork of Mark's plnkr). Note that now the axes are aligned on the center of the chart, as the center dot is perfectly on 0,0.


Related Query

More Query from same tag