Title and Axis labels

29,649

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.

Share:
29,649
DataByDavid
Author by

DataByDavid

Updated on July 09, 2022

Comments

  • DataByDavid
    DataByDavid almost 2 years

    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");