Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Title and Axis labels

I have been successful in creating labels for both the X and Y axis. I have also been successful in adding a title to the graph. My problem is that if I modify the margins of the graph, the label positions get messed up.

Snippet of where I change the margins of the graph:

    var margin = {top: 60, right: 60, bottom: 60, left:120}  

Snippet of where I create the labels:

    //Create Title 
    svg.append("text")
    .attr("x", w / 2 )
    .attr("y", 0)
    .style("text-anchor", "middle")
    .text("Title of Diagram");

    //Create X axis label   
    svg.append("text")
    .attr("x", w / 2 )
    .attr("y",  h + margin.bottom)
    .style("text-anchor", "middle")
    .text("State");

    //Create Y axis label
    svg.append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 0-margin.left)
    .attr("x",0 - (h / 2))
    .attr("dy", "1em")
    .style("text-anchor", "middle")
    .text("Revenue");  

JsFiddle:
http://jsfiddle.net/u63T9/

Here is another alternative, that I'm willing to live with:
I am basically leveraging the scales to find a base coordinate. I then add or take a little until I am happy with the location. This method actually keeps up with changes in the margins.

    //Create title 
    svg.append("text")
    .attr("x", w / 2 )
    .attr("y",  yScale(d3.max(input, function(d) { return d.CustomerCount; })) - 20 )
    .style("text-anchor", "middle")
    .text("Title of Graph");

    //Create X axis label   
    svg.append("text")
    .attr("x", w / 2 )
    .attr("y",  yScale(0) + 40 )
    .style("text-anchor", "middle")
    .text("State");

    //Create Y axis label
    svg.append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", xScale(0) - 80 )
    .attr("x",0 - (h / 2))
    .attr("dy", "1em")
    .style("text-anchor", "middle")
    .text("Revenue"); 
like image 926
DataByDavid Avatar asked Dec 15 '22 14:12

DataByDavid


1 Answers

I use a simple function to measure text and then compute margins based on that.

// create a dummy element, apply the appropriate classes,
// and then measure the element
function measure(text, classname) {
  if(!text || text.length === 0) return {height: 0, width: 0};

  var container = d3.select('body').append('svg').attr('class', classname);
  container.append('text').attr({x: -1000, y: -1000}).text(text);

  var bbox = container.node().getBBox();
  container.remove();

  return {height: bbox.height, width: bbox.width};
}

Now you can use

var titleSize = measure('my title', 'chart title'),
    margin.top = titleSize.height + 20; // add whatever padding you want 

I updated your example at http://jsfiddle.net/uzddx/2/. You can see the top margin resizes when you modify the font size of the title. You could do something similar for the left margin so that your label isn't so far away from the y-axis.

like image 184
Bill Avatar answered Jan 14 '23 15:01

Bill