[英]How to add non-overlapping polylines and text labels to 3D pie chart using d3.js?
[英]SVG / D3.js Add image in front of labels of a pie chart
我在这里有一个简单的饼图:
https://jsfiddle.net/5dexn2kn/1/
我尝试将图像附加到每个标签组
https://jsfiddle.net/5dexn2kn/2/
如您所见,由于text-anchor
可能是start
或end
,而且每个标签的文本长度也不同,所以我不知道如何查找图像并将其放置在正确的位置。
我该如何实现?
也许这会有所帮助: https : //jsfiddle.net/5dexn2kn/3/
输入文字ID:
labelG.append('text')
.attr('id', function(d) {
return d.data.label + '_text'
})
这必须是唯一的。 在这种情况下,它可以工作,但是如果您有时使用相同的标签,则不会。
然后获得相应标签文本的宽度,如下所示:
var thisText = document.getElementById(d.data.label + '_text') //select based on data, as id above is given from data
var thisTextWidth = thisText.clientWidth;
然后使用相同的逻辑来确定您是希望文本锚点start
还是end
来确定图像的位置:
if ((d.endAngle + d.startAngle) / 2 > Math.PI) {
return -35 - thisTextWidth;
} else {
return -25;
}
您可以使用getBoundingBox()
函数来实现此目的。
代码 :
labelG.append('image')
.attr('xlink:href', 'https://placekitten.com/20/20?.jpg')
.attr('height', 20)
.attr('width', 20)
.attr("x", function(d) {
var bbox = this.parentNode.getBBox();
return bbox.x;
})
.attr("y", function() {
var bbox = this.parentNode.getBBox();
return bbox.y;
});
labelG.selectAll("text").attr("dx", 25);
完整片段 :
const width = 400 const height = 400 const labelSpace = 50 const donutRadius = Math.min(width, height) / 2 const maxRadius = donutRadius + labelSpace const colorScheme = d3.scaleOrdinal(d3.schemeCategory20) const innerRadius = 20 const svgTranslate = [width / 2 + labelSpace * 2, height / 2 + labelSpace * 2] function getPercent(value, total) { return Math.round(value / total * 100) } const data = [{ label: 'aaaaaaa', value: 19 }, { label: 'bbb', value: 31 }, { label: 'c', value: 31 }, { label: 'ddddddddddd', value: 8 }, { label: 'eeee', value: 10 }] const total = data.map(d => d.value).reduce((a, b) => a + b) const svg = d3.select('#donutchart') .append('svg') .attr('width', width + maxRadius) .attr('height', height + maxRadius) .append('g') .attr('transform', `translate(${svgTranslate[0]}, ${svgTranslate[1]})`) const arc = d3.arc() .innerRadius(innerRadius) .outerRadius(donutRadius) const donut = d3.pie() .sort(null) .value(d => d.value) const arcG = svg.selectAll('g.arc-g') .data(donut(data)) .enter() .append('g') arcG.append('path') .attr('d', arc) .attr('fill', d => colorScheme(d.data.label)) const labelG = arcG.append('g') .attr('transform', d => { const c = arc.centroid(d) const x = c[0] * 2 const y = c[1] * 2 return `translate(${x}, ${y})` }) labelG.append('text') .attr('dy', '.35em') .html(d => `${d.data.label}<tspan class="label-percent"> ${getPercent(d.data.value, total)}%</tspan>` ) .attr('text-anchor', d => (d.endAngle + d.startAngle) / 2 > Math.PI ? 'end' : 'start' ) labelG.append('image') .attr('xlink:href', 'https://placekitten.com/20/20?.jpg') .attr('height', 20) .attr('width', 20) .attr("x", function(d) { var bbox = this.parentNode.getBBox(); return bbox.x; }) .attr("y", function() { var bbox = this.parentNode.getBBox(); return bbox.y; }); labelG.selectAll("text").attr("dx", 25);
body { font-family: San Francisco Display, sans-serif; } .label-percent { font-weight: bold; }
<div id="donutchart"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.3.0/d3.min.js"></script>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.