Estoy usando chart.js para hacer un gráfico de radar en el que el usuario debería poder interactuar por su cuenta. La idea es que si el usuario hace clic en el punto rojo, la aplicación debería saber si el punto verde es la intersección más cercana de las marcas y las líneas de ángulo, de modo que pueda cambiar el valor del conjunto de datos en el índice 1 (correspondiente a B) de 2 ( correspondiente a medio-bajo) a 4 (medio-alto).
Y está configurado así:
const chartData = { labels: ['A', 'B', 'C', 'D'], datasets: [{ fill: true, backgroundColor: 'rgba(6,211,248,0.5)', borderColor: 'rgb(6,211,248)', data: mockData.presetValues.a, }] }; const chartConfig = { type: 'radar', data: chartData, options: { elements: { line: { borderWidth: 3 }, }, scales: { r: { min: 0, max: 5, ticks: { stepSize: 1, callback: function (value) { return ['none', 'low', 'mid-low', 'mid', 'mid-high', 'high'][value] } }, grid: { circular: true, lineWidth: 5 }, angleLines: { color: 'black', } } }, plugins: { legend: { display: false } }, events: ['click'] } }; const actionChart = new Chart( canvas, chartConfig );Entonces tengo un oyente configurado así:
canvas.addEventListener('click', handleChartClick)Y finalmente tengo un controlador como este, que es donde está mi problema:
function handleChartClick(ev) { let clickPosition = Chart.helpers.getRelativePosition(ev, actionChart); console.log(clickPosition); //Find closest tick to click and change values in dataset before refresh }Después de horas de revisar la documentación y este sitio, no puedo encontrar una forma de correlacionar la posición del clic que recibo del método getRelativePosition con la posición de las intersecciones entre las líneas de ángulo y las marcas. Una vez que tenga esos dos datos, puedo modificar el conjunto de datos y actualizarlo, pero agradecería mucho que alguien pudiera ayudarme a encontrar la intersección más cercana al clic.
Puede usar la opción onClick del gráfico para capturar el evento de clic (en lugar de agregar un oyente al lienzo). De esta manera el evento pasado ya está normalizado.
La devolución de llamada podría ser algo así, para tener el tick más cercano:
options: { ... onClick(event, elements, chart) { const scale = chart.scales.r; const posY = Math.abs(scale.getDecimalForPixel(event.y) - 0.5); const posX = Math.abs(scale.getDecimalForPixel(event.x) - 0.5); const scalePosition = Math.max(posY, posX); const value = Math.round(scalePosition * 10); console.log(['none', 'low', 'mid-low', 'mid', 'mid-high', 'high'][value]); // shows value }, ...