自定义圆环图

问题描述

我正在尝试构建一个圆环图

我想要一个类似于下图的设计,其中值显示彩色饼图之间

import DonutChart from 'react-d3-donut';

    let data = [{
      count: 20,color: "red",name: 'My name' 
      },{
        count:30,color:"green",name:"yeys"
      },{
        count:20,color:"orange",name:"yeys"
      }]
      <DonutChart
innerRadius={90}
outerRadius={100}
transition={true}
svgClass="example1"
pieClass="pie1"
displayTooltip={true}
strokeWidth={3}
data={data} />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

are there any other libraries that helps me in building this design

解决方法

这是一个简单的 D3 圆环图:

const data = [
    {value: 20,text: 'First',color: 'red'},{value: 30,text: 'Second',color: 'green'},{value: 60,text: 'Third',color: 'blue'},];

const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));

const margin = 10;
const arcWidth = 30;
const radius = Math.min(width/2 - margin,height/2 - margin) - arcWidth / 2;
const center = {x: width / 2,y: height / 2};

let anglePos = 0;
const angleOffset = 0.025;

const sum = data.reduce((s,{value}) => s + value,0);
data.forEach(({value,text,color},index) => {
  const angle = Math.PI * 2 * value / sum;
  const start = {
    x: center.x + radius * Math.sin(anglePos + angleOffset),y: center.y + radius * -Math.cos(anglePos + angleOffset),};
  anglePos += angle;
  const end = {
    x: center.x + radius * Math.sin(anglePos - angleOffset),y: center.y + radius * -Math.cos(anglePos -angleOffset),};
  const flags = value / sum >= 0.5 ? '1 1 1' : '0 0 1';
  const pathId = `my-pie-chart-path-${index}`;
  svg.append('path')
    .attr('id',pathId)
    .attr('d',`M ${start.x},${start.y} A ${radius},${radius} ${flags} ${end.x},${end.y}`)
    .style('stroke',color)
    .style('fill','none')
    .style('stroke-width',arcWidth);
    
   svg.append('text')
    .attr('dy',6)
    .attr('text-anchor','middle')
    .append('textPath')
    .attr('startOffset',angle * radius / 2)
    .attr('href',`#${pathId}`)
    .text(text)
});
text {
  font-family: Calibri;
  font-size: 20px;
  font-weight: bold;
  fill: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

<svg width="200" height="200"></svg>

文本背景示例:

const data = [
    {value: 20,index) => {
    const angle = Math.PI * 2 * value / sum;
  const start = {
    x: center.x + radius * Math.sin(anglePos + angleOffset),${end.y}`)
    //.attr('stroke-linecap','round')
    .style('stroke',arcWidth);
    
  const textBg = svg.append('path');
     
    const textElement = svg.append('text')
    .text(text)
    .attr('dy','middle');
    
  const textBox = textElement.node().getBBox();
  textElement.text(null);
  const bgAngle = Math.abs(textBox.x) / radius;
  const midAngle = anglePos - angle / 2;
  const endBgAngle = midAngle + bgAngle;
  const startBg = {
    x: center.x + radius * Math.sin(midAngle - bgAngle),y: center.y + radius * -Math.cos(midAngle - bgAngle),};
  const endBg = {
    x: center.x + radius * Math.sin(midAngle + bgAngle),y: center.y + radius * -Math.cos(midAngle + bgAngle),};
textBg.attr('d',`M ${startBg.x},${startBg.y} A ${radius},${radius} 0 0 1 ${endBg.x},${endBg.y}`)
    .style('stroke','white')
    .style('fill','none')
    .attr('stroke-linecap','round')
    .style('stroke-width',arcWidth * 0.6);
  
  textElement.append('textPath')
    .text(text)
    .attr('startOffset',`#${pathId}`)
});
text {
  font-family: Calibri;
  font-size: 16px;
  fill: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>

<svg width="200" height="200"></svg>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...