我创建了一个圆环图,它可以正常工作,但现在我需要在其中心显示数字 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();
}
});
感谢您的帮助。
我尝试过这个并且有效
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;
我不相信 React Chart JS 有这个选项。但是,有一些自定义插件允许您在圆环图中插入自定义数据标签。请参阅本文档了解如何实现这一点。
从我从 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 />
组件),然后它将在重绘之前进行计算。
这是一个简单的解决方案:
步骤 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);
}
},
});
}
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();
},
},
]}
/>);
}
我之前尝试过 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();
}
}]
我尝试过杰伊的回答,一开始它不起作用,所以我必须对其进行一些更新,现在它可以工作了。
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();
},
}, ]}
我遇到了问题,结果是:
您可以使用“个人”物品阵列中的道具,将道具与时间结合起来。通过使用和使用效果,您可以构建与 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.