javascript - SVG/D3.js 在饼图标签前添加图片

标签 javascript d3.js svg

我这里有一个简单的饼图:
https://jsfiddle.net/5dexn2kn/1/

现在我想在每个标签前面添加一个图标,如下所示:
enter image description here

我尝试将图像附加到每个标签组
https://jsfiddle.net/5dexn2kn/2/

如你所见,因为text-anchor可能是startend,而且每个label的文本长度不同,我不知道如何找到图像并将其放置到正确的位置。

我怎样才能做到这一点?

最佳答案

您可以使用 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>

关于javascript - SVG/D3.js 在饼图标签前添加图片,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40341138/

相关文章:

svg - Rect 等价于 text 的 text-anchor 表示属性吗?

使用 SVG 和 anime.js 进行 CSS 转换

javascript - jQuery :contains() selector is not working IE

javascript - Typescript - 对象的条件属性

javascript - 替换已弃用的 `keypress` DOM 事件

javascript - SharePoint 2013 列表新表单不反射(reflect)修改后的更改

javascript - 按另一个索引数组对数组进行排序

javascript - 如何使用 nvd3、d3、javascript 错开子弹图

google-chrome - Chrome 是否错误地显示了这个 SVG 图案?

java - svg 亮度/透明度效果和滤镜 (Java Android)