D3 JS text upside down

Is it possible in this case to show the text not upside down?

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") ; 
+6
source share
2 answers

A great example is Placing texts on arcs using D3.js Nadih Bremer. A long blog with many images, of which the following excerpt:

Flip text on the bottom half

You can already feel how he finished with that look. But I find these marks along the bottom half that are upside down are pretty hard to read. Id prefer these shortcuts to be flipped, so I can read them from left to right again.

To do this, we need to switch the starting and ending coordinates of the current arc tracks along the lower half so that they are drawn from left to right. In addition, the sweep flag must be set to 0 to get an arc that works counterclockwise from left to right.

So, for the final act, add a few more lines of code to the .each () statement

 //Create the new invisible arcs and flip the direction for those labels on the bottom half .each(function(d,i) { //Search pattern for everything between the start and the first capital L var firstArcSection = /(^.+?)L/; //Grab everything up to the first Line statement var newArc = firstArcSection.exec( d3.select(this).attr("d") )[1]; //Replace all the commas so that IE can handle it newArc = newArc.replace(/,/g , " "); //If the end angle lies beyond a quarter of a circle (90 degrees or pi/2) //flip the end and start position if (d.endAngle > 90 * Math.PI/180) { var startLoc = /M(.*?)A/, //Everything between the capital M and first capital A middleLoc = /A(.*?)0 0 1/, //Everything between the capital A and 0 0 1 endLoc = /0 0 1 (.*?)$/; //Everything between the 0 0 1 and the end of the string (denoted by $) //Flip the direction of the arc by switching the start and end point (and sweep flag) var newStart = endLoc.exec( newArc )[1]; var newEnd = startLoc.exec( newArc )[1]; var middleSec = middleLoc.exec( newArc )[1]; //Build up the new arc notation, set the sweep-flag to 0 newArc = "M" + newStart + "A" + middleSec + "0 0 0 " + newEnd; }//if //Create a new invisible arc that the text can flow along svg.append("path") .attr("class", "hiddenDonutArcs") .attr("id", "donutArc"+i) .attr("d", newArc) .style("fill", "none"); }); 

The only thing that has changed from the previous section is the addition of the if statement. To flip the start and end positions, we can use some more regular expressions. The current initial location x and y is determined by everything that is between capital M and capital A. The current radius is denoted by everything located between capital A and 0 0 1 of the x-axis rotation, a large arc flag and a sweep flag. Finally, the final location is set by everyone between 0 0 1 and the end of the line (indicated by the $ symbol in the regular expression).

So, we save all fragments in different variables and create / replace newArc, using the end line in the if statement, which switched the start and end positions.

The TextPath section requires a small change. For the lower half arcs, the dy attribute should not raise marks above the arc tracks, but not drop marks below the arc tracks. Therefore, we need a small if statement, which will result in two different dy values. (To be able to use d.endAngle in an if statement, I replaced donutData with pie (donutData) in the .data () step. You can still reference the data itself using d.data, not just the d that you can see in the line .text () of the code.)

 //Append the label names on the outside svg.selectAll(".donutText") .data(pie(donutData)) .enter().append("text") .attr("class", "donutText") //Move the labels below the arcs for those slices with an end angle greater than 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;}); 
+7
source

It looks like when d3 creates one of those filled arcs, it actually creates a filled path shape that always (?) Starts on the right and continues clockwise - even if you cancel startAngle and endAngle.

If you manually create your own arc path and put your text on it, you can make it do the right thing.

 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+")"); // Radius of line text sits on. A value of 3.5 makes it slightly closer to the // outer radius (so text is placed in the middle of the blue line). var textpathRadius = (cfg.h / 3.5); // Make a path for the text to sit on that goes in an anti-clockwise direction. var textpath = g.append("svg:path") .attr("id","zzz") .style("display","none") .attr("d", "M -"+textpathRadius+" 0 A "+textpathRadius+" "+textpathRadius+" 0 0 0 "+textpathRadius+" 0") .attr("transform", "translate("+cfg.w/2+","+cfg.h/6+")"); var text = g.append("text") .style("font-size",30) .style("fill","#F8F8F8") .attr("dy",0) .append("textPath") .attr("xlink:href","#zzz") .attr("startOffset","50%") .style("text-anchor","middle") .text("some text"); 

I have never used d3, so it might be easier or cleaner to do what I did. But at least that should give you a place to start.

Updated script: http://jsfiddle.net/3DfVD/

+1
source

Source: https://habr.com/ru/post/945501/


All Articles