Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert padding so that points do not overlap with y or x-axis

Tags:

d3.js

I have the created this plot in D3: http://bl.ocks.org/cddesja/aee65f660c24cb2144fd

There are two things I would like to change.

1) I would like to make it so that none of my points overlap with the y or x-axis. I thought I could use transform() to create a little bit of a buffer but that creates a gap between the x and y axis lines, something I do not want. How should I do this correctly?

2) I would like to get rid of the tick marks at the intersection of the x and y lines. I am hoping that once I move the tick marks (and subsequently the pts and lines) that these tick marks automagically disappear. I don't know if that's really true or not.

Thanks in advance. Chris

like image 863
cdd Avatar asked Jan 19 '16 22:01

cdd


1 Answers

1.) This is controlled by the domain of your scales. Since your domains are set to the extent of the data, the axis starts there. Easy fix is to increase your domain to be +- N percent of the range. Also, I recommend remove the .nice() as you'll just end up fighting it for control the of the range.

// get extents and range
var xExtent = d3.extent(data, function(d) { return d.grade; }),
  xRange = xExtent[1] - xExtent[0],
  yExtent = d3.extent(data, function(d) { return d.bin; }),
  yRange = yExtent[1] - yExtent[0];

// set domain to be extent +- 5%
x.domain([xExtent[0] - (xRange * .05), xExtent[1] + (xRange * .05)]);
y.domain([yExtent[0] - (yRange * .05), yExtent[1] + (yRange * .05)]);

2.) This is controlled by the outerTickSize option. Just set it to zero.

var yAxisLeft = d3.svg.axis()
  .scale(y)
  .ticks(yTicks)
  .outerTickSize(0) //<-- set to zero
  .orient("left");

Full working code sample:

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<head>
	<title>Proportion of Students Suspended <body></body> Grade</title>
	<style type="text/css">
body {
  font: 10px Helvetica;
}
.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}
</style>

</head>
<body>
	<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>

	<script type="text/javascript">
// Set up the margins
var margin = {top: 50, right: 50, bottom: 30, left: 50},
    width = 1000 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom
    yTicks = 5

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

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

var xAxisBot = d3.svg.axis()
    .scale(x)
    .outerTickSize(0)
    .orient("bottom");

var xAxisTop = d3.svg.axis()
    .scale(x)
    .tickFormat('')
    .outerTickSize(0)
    .orient("top");

var yAxisLeft = d3.svg.axis()
    .scale(y)
    .ticks(yTicks)
    .outerTickSize(0)
    .orient("left");

var yAxisRight = d3.svg.axis()
    .scale(y)
    .ticks(yTicks)
    .tickFormat('')
    .outerTickSize(0)
    .orient("right");

var line = d3.svg.line()
    .x(function(d) { return x(d.grade); })
    .y(function(d) { return y(d.bin); });

var svg = d3.select("body").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 + ")");

var data = [{"grade":1,"bin":0.0398,"number":14943,"total":3.2306},{"grade":2,"bin":0.0605,"number":14128,"total":3.3778},{"grade":3,"bin":0.0777,"number":13590,"total":3.4621},{"grade":4,"bin":0.103,"number":13147,"total":3.7474},{"grade":5,"bin":0.1207,"number":12936,"total":3.7055},{"grade":6,"bin":0.202,"number":12857,"total":5.2757},{"grade":7,"bin":0.2534,"number":12962,"total":5.7908},{"grade":8,"bin":0.2561,"number":13362,"total":5.7759},{"grade":9,"bin":0.1873,"number":16618,"total":5.8429},{"grade":10,"bin":0.168,"number":14996,"total":5.4448},{"grade":11,"bin":0.1178,"number":13119,"total":4.3997},{"grade":12,"bin":0.0605,"number":12061,"total":3.8986}];

  var xExtent = d3.extent(data, function(d) { return d.grade; }),
      xRange = xExtent[1] - xExtent[0],
      yExtent = d3.extent(data, function(d) { return d.bin; }),
      yRange = yExtent[1] - yExtent[0];

  x.domain([xExtent[0] - (xRange * .05), xExtent[1] + (xRange * .05)]);
  y.domain([yExtent[0] - (yRange * .05), yExtent[1] + (yRange * .05)]);

  svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxisBot)
    .append("text")
      .attr("class", "label")
      .attr("x", width/2)
      .attr("y", 28)
      .style("text-anchor", "end")
      .text("Grade");

  svg.append("g")
      .attr("class", "x axis")
      .call(xAxisTop);

  svg.append("g")
      .attr("class", "y axis")
      .call(yAxisLeft)
    .append("text")
      .attr("class", "label")
      .attr("transform", "rotate(-90)")
      .attr("y", -40)
      .attr("x", -(height / 5))
      .attr("dy", ".71em")
      .style("text-anchor", "end")
      .text("Proportion of Students Suspended at Least Once");

  svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(" + width + ", 0)")
      .call(yAxisRight);

  svg.append("path")
      .datum(data)
      .attr("class", "line")
      .attr("d", line)
      .style("fill", "none")
      .style("stroke", "#3B3A35")
      .style("stroke-width", "1.5px");



  svg.selectAll(".dot")
      .data(data)
      .enter().append("circle")
      .attr("class", "dot")
      .attr("r", function(d) { return 10; })
      .attr("cx", function(d) { return x(d.grade); })
      .attr("cy", function(d) { return y(d.bin); })
      .attr("transform", "translate(0, 0)")
      .on("mouseover", function(d) {

          //Get this bar's x/y values, then augment for the tooltip
          var xPosition = parseFloat(d3.select(this).attr("cx")) + 0;
          var yPosition = parseFloat(d3.select(this).attr("cy")) + 0;

        d3.select(this)
            .transition()
            .duration(500)
            .style("fill-opacity", .35)
            .attr("r", 20)
         })
      .on("mouseout", function() {
          //Hide the tooltip
          d3.select(this)
            .transition()
            .duration(500)
            .style("fill-opacity", 1)
            .attr("r", function(d) { return 10; });
         })    
      .style("fill", "#3B3A35")
      .style("stroke", "#3B3A35")
      .style("stroke-width", "1.2px");
</script>
</body>
</html>
like image 93
Mark Avatar answered Nov 16 '22 03:11

Mark