Adding a line break to D3 graph y-axis labels
d3.js, javascript, svg, text
Solution
The problem is that you're adding the `tspan` elements as text without a namespace. This way they get interpreted as HTML. If you add them using D3 or explicitly create the elements with a namespace, it should work, i.e.
el.text('');
d3.select(el).append("tspan").text(sections[0]);
...
Problem
I am trying to add a line break to the y-axis labels on my D3 graph, which displays bandwidth moved. At the moment it displays inline `5 GB`, I would like it to display like so, ``` 5 GB ``` So, since there is no easy way of adding a line break to a svg text element, I opted for selecting all of the text elements after they have been rendered, I split them at the space and positioned them in `<tspan>` elements inside of the text element, with the `GB` positioned slightly lower than the value, which seemed to work, except for the labels not displaying at all, even though they did exist on the page. Here is a snippet of the code, ``` function init(svg,data,width,height,margin){ var x = d3.scale.linear() .domain([0,data[0].length-1]) .range([margin.left, width-margin.right]), y = d3.scale.linear() .domain([0,d3.max(data[0])]) .range([height-margin.bottom, margin.top]), /* Define stock x and y axis */ xAxis = d3.svg .axis() .ticks(data[0].length) .tickFormat(function(d) { return d+1; }) .scale(x) .orient('bottom'), yAxis = d3.svg .axis() .scale(y) .tickFormat(function(d) { return bytesToSize(d,0); }) .orient('right'), /* line path generator */ line = d3.svg.line().interpolate('monotone') .x(function(d,i) { return x(i); }) .y(function(d) { return y(d); }), /* area path generator */ area = d3.svg.area().interpolate('monotone') .x(line.x()) .y1(line.y()) .y0(y(0)), /* add the groups */ groups = svg.selectAll("g") .data(data) .enter() .append("g"); /* add the circles */ svg.select("g") .selectAll("circle") .data(data[0]) .enter() .append("circle") .attr("class","dot") .attr("cx", line.x()) .attr("cy", line.y()) .attr("r", 3.5) .style("fill","#008cc2") .style("stroke","#008cc2") .style("stroke-width","1.5px"); /* add the axes */ svg.append('g') .attr("class", "x axis") .attr("transform", "translate(0,"+(height - 20)+")") .call(xAxis) .selectAll("text") .style("text-anchor", "end") .attr("dx", "-.3em") .attr("dy", "-.3em") .attr("transform", function(d) { return "rotate(-90)" }); svg.append('g') .attr("class", "y axis") .call(yAxis); /* add the areas */ area = groups.append("path") .attr("class", "area") .attr("d",area) .style("opacity",0.3) .style("fill", function(d,i) { return (i == 0 ? "#008cc2" : "#7500c6" ); }); /* add the lines */ groups.append("path") .attr("class", "line") .attr("d", line) .style("fill","none") .style("stroke-width", "1.5px") .style("stroke", function(d,i) { return (i == 0 ? "#008cc2" : "#7500c6" ); }); var insertLinebreaks = function (d) { var el = $(d3.select(this).node()); var sections = bytesToSize(d,0); console.log(sections[0]); console.log(sections[1]); el.text(''); el.append('<tspan>'+sections[0]+'</tspan>'); el.append('<tspan x="0" dy="3">'+sections[1]+'</tspan>'); }; svg.selectAll('g.y.axis g text').each(insertLinebreaks); } function bytesToSize(bytes, precision) { var kilobyte = 1024; var megabyte = kilobyte * 1024; var gigabyte = megabyte * 1024; var terabyte = gigabyte * 1024; if ((bytes >= 0) && (bytes < kilobyte)) { return [bytes,'B']; } else if ((bytes >= kilobyte) && (bytes < megabyte)) { return [(bytes / kilobyte).toFixed(precision),'KB']; } else if ((bytes >= megabyte) && (bytes < gigabyte)) { return [(bytes / megabyte).toFixed(precision),'MB']; } else if ((bytes >= gigabyte) && (bytes < terabyte)) { return [(bytes / gigabyte).toFixed(precision),'GB']; } else if (bytes >= terabyte) { return [(bytes / terabyte).toFixed(precision),'TB']; } else { return [bytes,'B']; } } ``` Basically I would like to add a line break to a svg text element. I've tried a few methods, but to no avail.