我想在甜甜圈图表中插入额外的数据。控制器传递给视图的数组是这样的。
[
0 => array:3 [
"profit" => 20
"sex" => array:3 [
0 => 0
1 => 8
2 => 0
]
"count" => 8
]
1 => array:3 [
"profit" => 101.5
"sex" => array:3 [
0 => 4
1 => 4
2 => 0
]
"count" => 8
]
...
]
使用 chartjs
和所有数组元素的fied利润,我创建了这个甜甜圈图。
但我会定制这个图的内容 tooltip
使 "性别 "广告的数据可见。我试着用下面的代码,但可变的是 data
只包含图表中的值。
config.options.tooltips.callbacks = {
title: (tooltipItem, data) => {
return data['labels'][tooltipItem[0]['index']];
},
label: (tooltipItem, data) => {
return data['datasets'][0]['data'][tooltipItem['index']];
},
afterLabel: (tooltipItem, data) => {
var dataset = data['datasets'][0];
var percent = Math.round((dataset['data'][tooltipItem['index']] / dataset._meta[4].total) * 100)
return `${percent} %`;
},
backgroundColor: '#FFF',
titleFontSize: 16,
titleFontColor: '#0066ff',
bodyFontColor: '#000',
bodyFontSize: 14,
displayColors: false
}
我将数据传递给 config object
以此方式。config.data.datasets[0].data = data.map(el => el.profit);
我如何在工具提示中添加更多的数据,得到这样的东西?
这是我的代码。
function createDonatsChart(ctx, title, data, labels, middleText, type) {
Chart.pluginService.register({
beforeDraw: function(chart) {
if (chart.config.options.elements.center) {
// Get ctx from string
const ctx = chart.chart.ctx;
// Get options from the center object in options
const centerConfig = chart.config.options.elements.center;
const fontStyle = centerConfig.fontStyle || 'Asap';
const txt = centerConfig.text;
const color = centerConfig.color || '#000';
const maxFontSize = centerConfig.maxFontSize || 75;
const sidePadding = centerConfig.sidePadding || 20;
const sidePaddingCalculated = (sidePadding / 100) * (chart.innerRadius * 2)
// Start with a base font of 30px
ctx.font = `30px ${fontStyle}`;
// Get the width of the string and also the width of the element minus 10 to give it 5px side padding
const stringWidth = ctx.measureText(txt).width;
const elementWidth = (chart.innerRadius * 2) - sidePaddingCalculated;
// Find out how much the font can grow in width.
const widthRatio = elementWidth / stringWidth;
const newFontSize = Math.floor(30 * widthRatio);
const elementHeight = (chart.innerRadius * 2);
// Pick a new font size so it will not be larger than the height of label.
const fontSizeToUse = Math.min(newFontSize, elementHeight, maxFontSize);
const minFontSize = centerConfig.minFontSize;
const lineHeight = centerConfig.lineHeight || 25;
const wrapText = false;
if (minFontSize === undefined) {
minFontSize = 20;
}
if (minFontSize && fontSizeToUse < minFontSize) {
fontSizeToUse = minFontSize;
wrapText = true;
}
// Set font settings to draw it correctly.
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
const centerX = ((chart.chartArea.left + chart.chartArea.right) / 2);
const centerY = ((chart.chartArea.top + chart.chartArea.bottom) / 2);
ctx.font = `${fontSizeToUse}px ${fontStyle}`;
ctx.fillStyle = color;
if (!wrapText) {
ctx.fillText(txt, centerX, centerY);
return;
}
const words = txt.split(' ');
let line = '';
let lines = [];
// Break words up into multiple lines if necessary
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = ctx.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > elementWidth && n > 0) {
lines.push(line);
line = words[n] + ' ';
} else {
line = testLine;
}
}
// Move the center up depending on line height and number of lines
centerY -= (lines.length / 2) * lineHeight;
for (let n = 0; n < lines.length; n++) {
ctx.fillText(lines[n], centerX, centerY);
centerY += lineHeight;
}
//Draw text in center
ctx.fillText(line, centerX, centerY);
}
}
});
let config = {
type: 'doughnut',
data: {
datasets: [{
borderColor: '#121212',
borderWidth: 8,
backgroundColor: [
'#49C6E5',
'#EFC7C2',
'#00BD9D',
'#EF476F',
'#FFD166',
]
}],
labels: labels
},
options: {
responsive: true,
tooltips: {
},
legend: {
position: 'top',
onClick: null
},
title: {
display: true,
color: '#6c757d',
text: title,
fontFamily: "'Asap', san-serif",
fontSize: 20,
},
animation: {
animateScale: true,
animateRotate: true,
},
elements: {
center: {
text: middleText,
color: '#6c757d',
fontFamily: "'Asap', san-serif",
sidePadding: 20,
minFontSize: 12,
lineHeight: 25,
}
},
}
};
if ( type == 0 ) {
config.options.events = [];
config.data.datasets[0].data = data;
}
else {
// config.data.datasets[0].data = data.map(el => el.profit);
// config.options.tooltips.enabled = true;
// config.options.tooltips.callbacks = {
// title: (tooltipItem, data) => {
// return data['labels'][tooltipItem[0]['index']];
// },
// label: (tooltipItem, data) => {
// return data['datasets'][0]['data'][tooltipItem['index']];
// },
// afterLabel: (tooltipItem, data) => {
// var dataset = data['datasets'][0];
// var percent = Math.round((dataset['data'][tooltipItem['index']] / dataset._meta[4].total) * 100)
// return `${percent} %`;
// },
// backgroundColor: '#FFF',
// titleFontSize: 16,
// titleFontColor: '#0066ff',
// bodyFontColor: '#000',
// bodyFontSize: 14,
// displayColors: false
// }
config.data.datasets[0].data = data.map(el => el.profit);
}
Chart.defaults.global.defaultFontFamily = 'Asap';
Chart.defaults.doughnut.cutoutPercentage = 80;
new Chart(ctx, config);
}
const data = [
{
count: 8,
profit: 20,
sex: [0, 8, 0]
},
{
count: 8,
profit: 101.5,
sex: [4, 4, 0]
},
{
count: 1,
profit: 12.5,
sex: [1, 0, 0]
},
{
count: 2,
profit: 4,
sex: [2, 0, 0]
},
{
count: 5,
profit: 56.5,
sex: [5, 0, 0]
}
];
createDonatsChart(
document.getElementById('profitPerTarget').getContext('2d'),
'Target (di chi compra)',
data,
['14-17', '18-24', '25-30', '31-40', 'Over 40'],
`Totale ${(data.map(el => el.profit).reduce((a, b) => a + b, 0))} \u20AC`,
1
);
html, body {
background-color: #121212;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<canvas id="profitPerTarget" height="500" style="padding: 10px"></canvas>
你可以在createDonatsChart函数中使用closure。设置const为 const originalData = [...data]
然后你就可以在afterLabel回调中访问数据(如例)。
tooltips: {
callbacks: {
afterLabel: function(tooltipItem, data) {
const sexArray = originalData[tooltipItem['index']].sex
const precent = sexArray.reduce((a, b) => a + b, 0) // your calculation here
return '(' + precent + '%)';
}
}
}
请看playground中的例子。https:/jsfiddle.netdenisstukalovupw6asjm63#&commonjs=3CN0LJDjbl。