通常,StackOverflow 是我的最后手段,因为我不喜欢被惹恼,我想你也不喜欢,但我很绝望。
我想捕获图表栏上的点击,但我在日志中没有看到点击事件已被抛出的痕迹。我使用的是 Chart.js 2.8.9,但升级到 3.9,认为这可能是一个错误。
这是我加载图形的 vue 文件:
<template>
<div>
<h4>Gráficas de miembros activos</h4>
<div>
<!-- Pasamos chartData y el evento bar-clicked -->
<bar-chart :chart-data="datos" :opciones="opciones" @bar-clicked="handleBarClick" />
</div>
</div>
</template>
<script>
import BarChart from "../components/BarChart";
import api from "@/api";
export default {
name: "Graficas",
components: { BarChart },
data() {
return {
datos: {}, // Datos del gráfico
opciones: {} // Opciones del gráfico
};
},
methods: {
graficar: function (sector_id) {
api.graficas(sector_id).then((r) => {
this.datos = r.data;
// Configuración de colores y bordes de las barras
this.datos.datasets[0].backgroundColor = [
'rgba(255, 99, 132, 0.2)',
'rgba(255, 159, 64, 0.2)',
'rgba(255, 205, 86, 0.2)',
'rgba(75, 192, 192, 0.2)',
'rgba(54, 162, 235, 0.2)',
'rgba(153, 102, 255, 0.2)',
'rgba(201, 203, 207, 0.2)'
];
this.datos.datasets[0].borderColor = [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
];
this.datos.datasets[0].borderWidth = 1;
// Opciones del gráfico
this.opciones = {
scales: {
y: {
beginAtZero: true
}
},
responsive: true,
maintainAspectRatio: false,
height: 300
};
})
.catch(error => {
console.log(error);
});
},
handleBarClick({ data, dataIndex, datasetIndex }) {
// Este método captura el evento bar-clicked y muestra la información del clic
console.log(`Clicked bar at index ${dataIndex} in dataset ${datasetIndex}:`, data);
}
},
mounted() {
const sector_id = this.$route.params.id ?? 0;
this.graficar(sector_id);
},
};
</script>
这是我们创建的用于扩展 Chart.js 的类:
import { Chart, registerables } from 'chart.js';
Chart.register(...registerables); // Registro de todos los componentes necesarios
export default {
props: {
chartData: {
type: Object,
required: true
},
opciones: {
type: Object,
default: () => ({})
}
},
mounted() {
const canvas = this.$refs.canvas;
// Verificamos que el canvas existe y tiene contexto 2D
if (!canvas || !canvas.getContext) {
console.error("No se pudo obtener el contexto del canvas.");
return;
}
const ctx = canvas.getContext('2d');
// Configuración de las opciones de la gráfica
this.opciones.scales = {
y: {
beginAtZero: true
}
};
this.opciones.plugins = {
datalabels: {
color: "black",
textAlign: "center",
anchor: 'start',
font: {
weight: "bold",
size: 14,
}
}
};
this.opciones.responsive = true;
this.opciones.maintainAspectRatio = false;
this.opciones.hover = {
mode: 'nearest',
intersect: true
};
this.opciones.interaction = {
mode: 'index',
intersect: false
};
// Establecemos una altura fija para el canvas a través de CSS
canvas.style.height = '400px';
canvas.style.width = '100%';
// Instancia del gráfico
this.chartInstance = new Chart(ctx, {
type: 'bar',
data: this.chartData,
options: {
...this.opciones,
onClick: (event, elements) => {
console.log('onClick event triggered');
if (elements.length > 0) {
const element = elements[0];
const dataIndex = element.index;
const datasetIndex = element.datasetIndex;
console.log('Data point clicked:', dataIndex, datasetIndex);
const data = this.chartData.datasets[datasetIndex].data[dataIndex];
this.$emit('bar-clicked', { data, dataIndex, datasetIndex });
} else {
console.log('No elements clicked.');
}
}
}
});
},
watch: {
chartData(newData) {
if (this.chartInstance) {
this.chartInstance.data = newData;
this.chartInstance.update();
}
},
opciones(newOptions) {
if (this.chartInstance) {
this.chartInstance.options = newOptions;
this.chartInstance.update();
}
}
},
beforeDestroy() {
if (this.chartInstance) {
this.chartInstance.destroy();
}
},
render(h) {
return h('canvas', { ref: 'canvas' });
}
};
后端返回的JSON很简单,所以错误不应该出现:
{
"datasets": [
{
"data": [
15,
5,
0,
0,
0
],
"label": "Sector San Felipe De Jesus"
}
],
"labels": [
"Matrimonios",
"MaRes",
"J\u00f3venes",
"Adolescentes",
"Asistentes Eclesiales"
]
}
以防万一它发生在其他人身上。有两个阻碍:
canvas.onclick = (evt) => {
const res = chart.getElementsAtEventForMode(
evt,
'nearest',
{ intersect: true },
true
);
// If didn't click on a bar, `res` will be an empty array
if (res.length === 0) {
return;
}
// Alerts "You clicked on A" if you click the "A" chart
alert('You clicked on ' + chart.data.labels[res[0].index]);
};