在 React-Chartjs-2 框的圆环图中添加文本以进行反应

问题描述 投票:0回答:8

我创建了一个圆环图,它可以正常工作,但现在我需要在其中心显示数字 45。

我应该在哪里注明要显示的文字和坐标?在图表的选项中?

我正在使用反应组件

class DoughnutChart extends React.Component {

  render() {
    const data = {
      datasets: [{
      data: [],
      backgroundColor: [
        '#999',
        '#eee'
      ]
    }],
     text: '45'
  };
    return (
       <Doughnut data={data} />
    );
  }
};

export default DoughnutChart;

编辑

我找到了这个插件,但我找不到它如何应用于react组件

//Plugin for center text
Chart.pluginService.register({
  beforeDraw: function(chart) {
    var width = chart.chart.width,
    height = chart.chart.height,
    ctx = chart.chart.ctx;
    ctx.restore();
    var fontSize = (height / 160).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "top";
    var text = "Foo-bar",
    textX = Math.round((width - ctx.measureText(text).width) / 2),
    textY = height / 2;
    ctx.fillText(text, textX, textY);
    ctx.save();
  }
});

感谢您的帮助。

javascript reactjs pie-chart react-chartjs
8个回答
14
投票

我尝试过这个并且有效

import { Doughnut } from "react-chartjs-2";

function DoughnutChart() {

 const data = {...}

 const options = {...}

 const plugins = [{
     beforeDraw: function(chart) {
      var width = chart.width,
          height = chart.height,
          ctx = chart.ctx;
          ctx.restore();
          var fontSize = (height / 160).toFixed(2);
          ctx.font = fontSize + "em sans-serif";
          ctx.textBaseline = "top";
          var text = "Foo-bar",
          textX = Math.round((width - ctx.measureText(text).width) / 2),
          textY = height / 2;
          ctx.fillText(text, textX, textY);
          ctx.save();
     } 
   }]



  return (
   
        <Doughnut 
          type="doughnut" 
          data={data} 
          options{options} 
          plugins={plugins} 
         />
  );
}

export default DoughnutChart;

3
投票

我不相信 React Chart JS 有这个选项。但是,有一些自定义插件允许您在圆环图中插入自定义数据标签。请参阅本文档了解如何实现这一点。

ChartJS 插件数据标签


2
投票

从我从 react-chartjs-2 看到的,它只有这些属性:

data: (PropTypes.object | PropTypes.func).isRequired,
width: PropTypes.number,
height: PropTypes.number,
id: PropTypes.string,
legend: PropTypes.object,
options: PropTypes.object,
redraw: PropTypes.bool,
getDatasetAtEvent: PropTypes.func,
getElementAtEvent: PropTypes.func,
getElementsAtEvent: PropTypes.func
onElementsClick: PropTypes.func, // alias for getElementsAtEvent (backward compatibility)

它们似乎都不是您可以传递以在中间显示您的号码的文本。您可以使用 legend 道具并操纵为图例创建的对象,以使用 css 移动它,或者在渲染中使用另一个 div 来显示数字,然后将其设置为图表内的样式。

您可以执行此操作的另一种方法是将 Donut 组件包装在一个 div 中,并在该 div 中包含另一个包含文本的子组件,如下所示:

    return( 
    <div className='wrapper'> 
        <div className='chart-number'>{this.state.text}</div>
        <Doughnut data={data} />
    </div>)

在你的CSS中,你必须弄清楚如何将图表编号div放置在包装器div的中间,其中将包含图表。

如果您刚刚开始使用这个库,也许可以寻找一个适合您需求的不同库,这样您就不必围绕它编写代码!

希望这有帮助:)

编辑1:

据我所知,您可能需要以某种方式将

Chart.pluginService.register
代码连接到您的图形对象(即
<Doughnut />
组件),然后它将在重绘之前进行计算。


2
投票

这是一个简单的解决方案:

步骤 01: 在您的选项中添加此选项

options: {
        centerText: {
            display: true,
            text: `90%`
        }
      .....
      .....

步骤02: 创建一个新方法drawInnerText

drawInnerText = (chart) => {

    var width = chart.chart.width,
        height = chart.chart.height,
        ctx = chart.chart.ctx;

    ctx.restore();
    var fontSize = (height / 114).toFixed(2);
    ctx.font = fontSize + "em sans-serif";
    ctx.textBaseline = "middle";

    var text = chart.config.options.centerText.text,
        textX = Math.round((width - ctx.measureText(text).width) / 2),
        textY = height / 2;

    ctx.fillText(text, textX, textY);
    ctx.save();
}

步骤03:调用drawInnerText

componentWillMount() {
        Chart.Chart.pluginService.register({
            beforeDraw: function (chart) {                    
                if (chart.config.options.centerText.display !== null &&
                    typeof chart.config.options.centerText.display !== 'undefined' &&
                    chart.config.options.centerText.display) {
                    this.drawInnerText(chart);
                }
            },
        });
    }

2
投票
function DoughnutChart({ data = {} }) {
 return (
   <Doughnut
     data={format(dataObj)}
     plugins={[
      {
        beforeDraw(chart) {
         const { width } = chart;
         const { height } = chart;
         const { ctx } = chart;
         ctx.restore();
         const fontSize = (height / 160).toFixed(2);
         ctx.font = `${fontSize}em sans-serif`;
         ctx.textBaseline = 'top';
         const { text } = "23";
         const textX = Math.round((width - ctx.measureText(text).width) / 2);
         const textY = height / 2;
         ctx.fillText(text, textX, textY);
         ctx.save();
       },
     },
   ]}
 />);

}


0
投票

我之前尝试过 Jays Answer,但现在它不再起作用了。 您需要在插件数组中指定一个 id。

 const plugins = [{
 id : 'here comes your id for the specific plugin',
 beforeDraw: function(chart) {
  var width = chart.width,
      height = chart.height,
      ctx = chart.ctx;
      ctx.restore();
      var fontSize = (height / 160).toFixed(2);
      ctx.font = fontSize + "em sans-serif";
      ctx.textBaseline = "top";
      var text = "Foo-bar",
      textX = Math.round((width - ctx.measureText(text).width) / 2),
      textY = height / 2;
      ctx.fillText(text, textX, textY);
      ctx.save();
 } 

}]


0
投票

我尝试过杰伊的回答,一开始它不起作用,所以我必须对其进行一些更新,现在它可以工作了。

const plugins = {[
{
  id:"Id here",
  beforeDraw:function(chart:any) {
    let ctx = chart.ctx;
    let xAxis = chart.scales.x;
    let yAxis = chart.scales.y;
    let maxValue = Math.max(...chart.data.datasets[0].data);
    let minValue = Math.min(...chart.data.datasets[0].data);
    ctx.save();
    ctx.textAlign = 'center';
    ctx.font = '14px Roboto';
    ctx.fillStyle = 'blue';
    ctx.textAlign = 'left';
    ctx.fillText('Text1 = ', xAxis.left , yAxis.top + 15);
    ctx.fillText('Text2 = ', xAxis.left , yAxis.top + 40);
    ctx.fillText(maxValue + '°C', xAxis.left + 200, yAxis.top + 15);
    ctx.fillText(minValue + '°C', xAxis.left + 200, yAxis.top + 40);
    ctx.restore();
 },

}, ]}


0
投票

我遇到了问题,结果是:

您可以使用“个人”物品阵列中的道具,将道具与时间结合起来。通过使用和使用效果,您可以构建与 Doughnut 组件所需的结构相关的对象数组。 如果他尝试使用插件来保护数组插件,则可以使用插件的变量来保护插件.text。 Entonces cuando mi prop Personal cambie deberia tambien setear este array con un nuevo texto en base a la cantidad de individual.

function DailyInfo({
  todayDate,
  units,
  personal,
  entornos,
  observaciones
}) {
  const [dataPersonalArea, setDataPersonalArea] = useState({})
  const [plugin, setPlugin] = useState([])

  useEffect(() => {

    if (personal.length > 0) {
      //Estructuro la info para el grafico
      let personalByArea = findPersonalAreaNumber(personal);

      //Seteo la info estructurada en un estado
      setDataPersonalArea(personalByArea);

      //La variable plugins me va servir para poner el texto en medio del grafico
      const plugins = [{
        beforeDraw: function(chart) {
          var width = chart.width,
            height = chart.height,
            ctx = chart.ctx;
          ctx.restore();
          var fontSize = (height / 160).toFixed(2);
          ctx.font = fontSize + "em sans-serif";
          ctx.textBaseline = "center";

          //Aquí le paso la el total de personas al valor de texto
          var text = personal.length,
            textX = Math.round((width - ctx.measureText(text).width) / 2),
            textY = (height / 2) + 45;
          ctx.fillText(text, textX, textY);
          ctx.save();
        }
      }]
      //seteo el array de plugins con el texto correspondiente
      setPlugin(plugins)
    }

  }, [personal]);


  return ( < div className = {
      style.todaySalesContainer
    } >
    <
    h3 > Hoy: {
      todayDate
    } < /h3>

    {
      dataPersonalArea.labels && < Doughnut data = {
        dataPersonalArea
      }
      plugins = {
        plugin
      }
      />} < /
      div > )

  }

PD:Yase que debería hacerlo en otro useEffect alone estaba probando comosolver el Problema.

© www.soinside.com 2019 - 2024. All rights reserved.