在文本

时间:2017-03-22 09:52:29

标签: javascript d3.js svg

所以我使用D3.js并且我有一个雷达图表,其数据由位于圆圈内的文本表示。

文本总是有不同的长度,我希望在每个文本后按这个顺序添加一个图标:图表,文本标签,垃圾桶。

我已经尝试在呈现文本的属性中计算长度,这正确地给出了每个标签的长度,但是我没有设法附加图标:

.attr("lenght", function() {
          var datalong = this.getComputedTextLength();
       })

然后我也尝试单独附加图标,但是我不知道如何获得长度:

axis.append("svg:image")
        .attr("xlink:href","http://svgur.com/i/121.svg")
        .attr("y",-7)
        .attr("opacity",1)
        .attr("transform", function(d, i,e) {
          var angleI = angleSlice * i * 180 / Math.PI - 90; 
          var distance = radius * options.trash.trashFactor; 
          var flip = angleI > 90 ? 180 : 0; 
          return "rotate(" + angleI + ") translate(" + distance + ")" + "rotate(" + flip + ")"
        });

然后我尝试在我写数据(文本)的方法中附加图标,但图标没有显示出来。我试图将它们分组并将它们放在一起,但也没有成功。

我有一个JSFiddle,有一些我能得到的最接近的选项。我希望有可能理解我想要做什么,如果没有,请参考小提琴,你可以很容易地理解我想要实现的目标。

JSFiddle:https://jsfiddle.net/fsb47ndf/5/

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:3)

这是另一个想法,使用FontAwesome字体和图标。这样就可以避免附加svg:image。

.html(function (d, i) {
    var angleI = angleSlice * i * 180 / Math.PI - 90;
    if (angleI > 90) {
        return ' ' + d;
    } else {
        return d + ' '
    }
});    

https://jsfiddle.net/fsb47ndf/25/

&#xf014是垃圾桶图标(http://fontawesome.io/icon/trash-o/)的FA unicode。以与旋转文本相同的方式旋转图标。

答案 1 :(得分:2)

你可以通过这个繁琐的数学来获得文本的长度:

var textLength = d3.select(this.parentNode).select("text").node().getComputedTextLength();

基本上,这就是代码的作用:

  • d3.select(this.parentNode):选择图标的父级,然后选择......
  • select("text").node():它选择该父母的孩子的文本,最后......
  • getComputedTextLength():获取该文字的长度。

然后,您可以使用它来设置图标的距离:

    var distance = angleI > 90 ? radius + textLength + 40 : radius + textLength + 30;

这是您更新的小提琴:https://jsfiddle.net/0L4xzmfo/

这里的代码片段中的代码相同:

 data = [{
   name: 'DATA11111',
   value: 22,
 }, {
   name: 'DATA2',
   value: 50,
 }, {
   name: 'DATA33333333',
   value: 0,
 }, {
   name: 'DATA444444',
   value: 24,
 }, {
   name: 'DATA55',
   value: 22,
 }, {
   name: 'DATA6666',
   value: 30,
 }, {
   name: 'DATA7',
   value: 20,
 }, {
   name: 'DATA8',
   value: 41,
 }, {
   name: 'DATA9',
   value: 31,
 }, {
   name: 'DATA10',
   value: 30,
 }, {
   name: 'DATA1121213213',
   value: 30,
 }, {
   name: 'DATA12',
   value: 30,
 }, {
   name: 'DATA1123123212313',
   value: 30,
 }, {
   name: 'DATA14',
   value: 30,
 }, ];



 var options = {

   width: 600,
   height: 600,

   margins: {
     top: 100,
     right: 100,
     bottom: 100,
     left: 100
   },

   circles: {
     levels: 6,
     maxValue: 100,
     labelFactor: 1.15,
     dataFactor: 1.09,
     opacity: 0.2,
   },

   trash: {
     trashFactor: 1.32
   }

 };


 var allAxis = (data.map(function(i, j) {
     return i.name
   })),
   total = allAxis.length,
   radius = Math.min(options.width / 2, options.height / 2),
   angleSlice = Math.PI * 2 / total,
   Format = d3.format('');

 var rScale = d3.scale.linear()
   .domain([0, options.circles.maxValue])
   .range([50, radius]);

 var svg = d3.select("body").append("svg")
   .attr("width", options.width + options.margins.left + options.margins.right)
   .attr("height", options.height + options.margins.top + options.margins.bottom);

 var g = svg.append("g")
   .attr("transform", "translate(" + (options.width / 2 + options.margins.left) + "," + (options.height / 2 + options.margins.top) + ")");

 var axisGrid = g.append("g")
   .attr("class", "axisWraper");

 var axis = axisGrid.selectAll(".axis")
   .data(allAxis)
   .enter()
   .append("g")
   .attr("class", "axis")

 //append them lines
 axis.append("line")
   .attr("x1", 0)
   .attr("y1", 0)
   .attr("x2", function(d, i) {
     var tempX2 = radius * Math.cos(angleSlice * i - Math.PI / 2);
     return tempX2;
   })
   .attr("y2", function(d, i) {
     var tempY = radius * Math.sin(angleSlice * i - Math.PI / 2);
     return tempY;
   })
   .attr("class", "line")
   .attr("stroke", "black")
   .attr("fill", "none");

 //Draw background circles
 axisGrid.selectAll(".levels")
   .data([6, 5, 4, 3, 2, 1])
   .enter()
   .append("circle")
   .attr("class", "gridCircle")
   .attr("r", function(d, i) {
     return parseInt(radius / options.circles.levels * d, 10);
   })
   .attr("stroke", "black")
   .attr("fill-opacity", options.circles.opacity);

 //Write data
 axis.append("text")
   .attr("class", "labels")
   .attr("font-size", "12px")
   .attr("font-family", "Montserrat")
   .attr("text-anchor", function(d, i) {
     var angleI = angleSlice * i * 180 / Math.PI - 90;
     return angleI > 90 ? "end" : "start"
   })
   .attr("dy", ".35em")
   .attr("fill", "black")
   .attr("transform", function(d, i) {
     var angleI = angleSlice * i * 180 / Math.PI - 90; // the angle to rotate the label
     var distance = radius * options.circles.dataFactor; // the distance from the center
     var flip = angleI > 90 ? 180 : 0; // 180 if label needs to be flipped
     return "rotate(" + angleI + ") translate(" + distance + ")" + "rotate(" + flip + ")"
   })
   .text(function(d) {
     return d;
   });


 axis.append("svg:image")
   .attr("xlink:href", "http://svgur.com/i/121.svg")
   .attr("class", "trash")
   .attr("y", -7)
   .attr("text-anchor", "end")
   .attr("transform", function(d, i) {
     var textLength = d3.select(this.parentNode).select("text").node().getComputedTextLength();
     var angleI = angleSlice * i * 180 / Math.PI - 90; // the angle to rotate the label
     var distance = angleI > 90 ? radius + textLength + 40 : radius + textLength + 30; // the distance from the center
     var flip = angleI > 90 ? 180 : 0; // 180 if label needs to be flipped
     return "rotate(" + angleI + ") translate(" + distance + ")" + "rotate(" + flip + ")"
   });
.trash {
  position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

PS:我正在使用一个神奇的数字,因为我没有查看代码来找到文本的确切填充。请相应更改该幻数。