svg - D3 JS upside down path text -
is possible show text not upside down in case?
http://jsfiddle.net/paulocoelho/hzsm8/1/
code:
var cfg = { w:400, h:400 }; var g = d3.select("#testdiv").append("svg").attr("width", cfg.w).attr("height", cfg.h).append("g") var arct = d3.svg.arc() .innerradius(cfg.h / 5) .outerradius(cfg.h / 3) .startangle(math.pi/2) .endangle(math.pi*1.5); var path = g.append("svg:path") .attr("id","yyy") .attr("d", arct) .style("fill","blue") .attr("transform", "translate("+cfg.w/2+","+cfg.h/6+")"); var text = g.append("text") .style("font-size",30) .style("fill","#f8f8f8") .attr("dy",35) .append("textpath") .attr("xlink:href","#yyy") .attr("startoffset",50) .text("some text") ;
a great example placing texts on arcs d3.js nadieh bremer. lengthy blog many images following extract:
flipping text on bottom half
you feel it’s finished look. find labels along bottom half, upside down, rather hard read. i’d prefer if labels flipped, can read them left right again.
to accomplish this, need switch start , end coordinates of current arc paths along bottom half drawn left right. furthermore, sweep-flag has set 0 arc runs in counterclockwise fashion left right
so final act, let’s add few more lines of code .each() statement
//create new invisible arcs , flip direction labels on bottom half .each(function(d,i) { //search pattern between start , first capital l var firstarcsection = /(^.+?)l/; //grab first line statement var newarc = firstarcsection.exec( d3.select(this).attr("d") )[1]; //replace commas ie can handle newarc = newarc.replace(/,/g , " "); //if end angle lies beyond quarter of circle (90 degrees or pi/2) //flip end , start position if (d.endangle > 90 * math.pi/180) { var startloc = /m(.*?)a/, //everything between capital m , first capital middleloc = /a(.*?)0 0 1/, //everything between capital , 0 0 1 endloc = /0 0 1 (.*?)$/; //everything between 0 0 1 , end of string (denoted $) //flip direction of arc switching start , end point (and sweep flag) var newstart = endloc.exec( newarc )[1]; var newend = startloc.exec( newarc )[1]; var middlesec = middleloc.exec( newarc )[1]; //build new arc notation, set sweep-flag 0 newarc = "m" + newstart + "a" + middlesec + "0 0 0 " + newend; }//if //create new invisible arc text can flow along svg.append("path") .attr("class", "hiddendonutarcs") .attr("id", "donutarc"+i) .attr("d", newarc) .style("fill", "none"); });
the thing has changed since previous section addition of if statement. flip start , end positions, can use few more regular expressions. current starting x , y location given in between capital m , capital a. current radius denoted in between capital , 0 0 1 of x-axis rotation, large-arc flag , sweep flag. end location given in between 0 0 1 , end of string (denoted $ in regex).
so save pieces in different variables , build/replace newarc using final line in if statement has switched start , end position.
the textpath section needs small change. bottom half arcs, dy attribute shouldn’t raise labels above arc paths, lower labels below arc paths. need small if statement result in 2 different dy values. (to able use d.endangle in if statement replaced donutdata pie(donutdata) in .data() step. can still reference data using d.data instead of d, can see in .text() line of code.)
//append label names on outside svg.selectall(".donuttext") .data(pie(donutdata)) .enter().append("text") .attr("class", "donuttext") //move labels below arcs slices end angle greater 90 degrees .attr("dy", function(d,i) { return (d.endangle > 90 * math.pi/180 ? 18 : -11); }) .append("textpath") .attr("startoffset","50%") .style("text-anchor","middle") .attr("xlink:href",function(d,i){return "#donutarc"+i;}) .text(function(d){return d.data.name;});
Comments
Post a Comment