所以我使用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/
非常感谢任何帮助!
答案 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:我正在使用一个神奇的数字,因为我没有查看代码来找到文本的确切填充。请相应更改该幻数。