简体   繁体   中英

Simple curved text within a circle

I have a matrix of circles that I created like this:

  var maxColumn = 6;

  graphGroup.selectAll('circle')
      .data(data)
      .enter()
      .append('circle')
      .attr('id', function(d,i) {return 'c'+String(i)})
      .attr('cx', function(d, i) {
          return (i % maxColumn) * 200
      })
      .attr('cy', function(d, i) {
          return ~~((i / maxColumn) % maxColumn) * 180
      })
      .attr('r', function(d) {return rScale(d.Trust)})
      .style('fill', '#003366');

Then I wanted to try and append curved text within each circle with the date corresponding to that circle. I thought all I had to do was reference a curved svg element for the text to curve using .attr("xlink:href",function(d,i){return "#c"+i;}) but actually nothing was appended at all. Here is the text portion:

      graphGroup.selectAll('text')
        .data(data)
        .enter()
        .append("text")
        .style("font-size",20)
        .append("textPath")
        .attr("textLength",function(d,i){return 100 ;})
        .attr("xlink:href",function(d,i){return "#c"+i;})
        .attr("startOffset",function(d,i){return 3/20;})
        .attr("dy","-1em")
        .text(function(d){return d.date;})

Question

Is there an easier way to add curved text to each of my circles, or what is a sensible way to proceed?

As the name implies, a <textPath> must be used with a <path> element. You cannot use it with a <circle> . If you look at the SVG specifications :

In addition to text drawn in a straight line, SVG also includes the ability to place text along the shape of a 'path' element. To specify that a block of text is to be rendered along the shape of a 'path', include the given text within a 'textPath' element which includes an 'xlink:href' attribute with an IRI reference to a 'path' element.

Note: that's for SVG 1, for SVG 2 see the comment below .

Therefore, you have to create paths. You can convert your circles to paths dealing with the d attribute. For instance, supposing your cx = 100 , cy = 100 and r = 30 , this would be the d attribute:

d = "M70,100 a 30,30 0 1,0 60,0 a 30,30 0 1,0 -60,0";

There are several online resources explaining how do you calculate the d attribute based on cx , cy and r , like this one .

Here is a demo:

 const svg = d3.select("svg"); const circle = svg.append("path") .style("fill", "none") .style("stroke", "black") .attr("d", "M70,100 a 30,30 0 1,0 60,0 a 30,30 0 1,0 -60,0"); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg></svg> 

Now you can append the <textPath> :

 const svg = d3.select("svg"); const circle = svg.append("path") .style("fill", "none") .style("stroke", "black") .attr("d", "M70,100 a 30,30 0 1,0 60,0 a 30,30 0 1,0 -60,0") .attr("id", "myPath"); const textpath = svg.append("text") .append("textPath") .attr("xlink:href", "#myPath") .text("Foo Bar Baz") 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <svg></svg> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM