大菜鸟警报!!...大家好,今天大家好。我想做的是使用.getElementsAtEvent
函数来提醒图点。
JS系统
"use strict";
Vue.component('v-select', VueSelect.VueSelect);
const ChartDefinition = [
{
title: 'Bar',
multiSeries: true,
hasYAxis: true,
stackable: true,
},
{
title: 'Line',
multiSeries: true,
hasYAxis: true,
curve: true,
fill: true
},
{
title: 'Doughnut'
},
{
title: 'Pie'
},
{
title: 'Radar',
multiSeries: true,
fill: true
},
{
title: 'Scatter',
multiSeries: true,
hasYAxis: true,
scatterTransform: true
}
]
var app = new Vue({
el: '#app',
data() {
return {
completed: false, // Whether csv file is selected
largeFileMode: false, // Large file mode limits the CSV preview size and stop automatic rendering after changing any options
html: '', // For storing chart configurations when exporting as html
chartId: 0, // For storing a random number when exporting as html
fileName: '', // For storing to file name to be displayed in heading
rendered: false, // Whether chart has been rendered
raw: [], // Raw csv data parsed by papaparse
header: [], // First row of the raw csv data as series name
preview: [], // First 8 cols and 16 rows of the CSV data for preview under large file mode
fileReadRange: '', // Limit range to read from A1:???
selected: [], // Selected data series
chartType: 'Bar', // Selected chart type
chart: {}, // Active chart object (kept for destruction after updating chart types or options)
// Valid chart options objects
chartDefinition: ChartDefinition, // Valid chart options for each chart type
activeChartDefinition: {}, // Valid chart options available for the selected chart type. Updated by updateChartType()
// Variables storing chart options
chartOption_beginAtZero: true, // valid for chart with hasYAxis. Specifies whether y-axis of chart must include 0
chartOption_curve: true, // valid for chart with curve. Specifies whether or not to smooth the curve
chartOption_fill: false, // valid for chart with fill. Specifies whether area under curve should be filled
chartOption_stack: false, // valid for chart with stackable. Specifies whether series should be stacked
chartOption_chartTitle: false, // valid for all chart types. Specifies whether chart title should be displayed
chartOption_chartTitleText: '', // valid for all chart types. Specifies the chart title text
chartOption_yAxisLabel: false, // valid for chart with hasYAxis. Specifies whether y-axis label should be displayed
chartOption_yAxisLabelText: '', // valid for chart with hasYAxis. Specifies the y-axis label text
chartOption_xAxisLabel: false, // valid for chart with hasYAxis. Specifies whether x-axis label should be displayed
chartOption_xAxisLabelText: '', // valid for chart with hasYAxis. Specifies the x-axis label text
// Zoom options
zoomX: false,
zoomY: false,
}
},
methods: {
/**
* Loads and parses csv file.
*/
load() {
this.completed = false;
this.rendered = false;
// Resets variables on load
this.raw = [];
this.header = [];
this.selected = [];
if (this.chart instanceof Chart) this.chart.destroy();
let readRange = {};
if (this.fileReadRange != null) readRange = this.getNumColsFromA1(this.fileReadRange);
console.log(`Will read ${ readRange.numCols > 0 ? 'first ' + readRange.numCols : 'all'} columns and ${ readRange.numRows > 0 ? 'first ' + readRange.numRows : 'all'} rows.`);
this.fileReadRange = readRange.col + (readRange.numRows > 0 ? readRange.numRows : '');
const selectedFile = document.getElementById('myfile').files[0];
console.log(selectedFile.name);
this.fileName = selectedFile.name;
Papa.parse(selectedFile, {
skipEmptyLines: true,
preview: readRange.numRows > 0 ? readRange.numRows : 0,
complete: (results) => {
console.log('Finished:', results.data);
this.raw = results.data;
this.limitColumns(readRange.numCols > 0 ? readRange.numCols : 0);
this.header = Array.from(this.raw[0]); // problem: duplicated / null headers
this.header.shift();
this.refreshPreview();
this.completed = true;
console.log(this.completed);
}
});
},
/**
* Renders chart.
*
* @param {Boolean} force Whether or not to run a manual render in large file mode. Defaults to false.
* This option has no effect if large file mode is not activated.
* @param {Boolean} refreshHtml Whether or not to refresh the exportable HTML. Defaults to false.
*/
render(force = false, refreshHtml = false) {
this.registerTooltips();
if (!this.completed) return; // Do nothing if file not loaded
if (this.largeFileMode && !force) return;
console.log('Trying to render!');
let transformed = this.transform();
let datasets = [];
transformed.series.map( (series) => {
datasets.push({
label: series.seriesName,
lineTension: (this.activeChartDefinition.curve && this.chartOption_curve) ? 0.4 : 0,
fill: this.chartOption_fill,
data: series.data
})
});
this.rendered = true;
// Graph!!
let ctx = document.getElementById('csv-chart').getContext('2d');
if (this.chart instanceof Chart) this.chart.destroy();
let chartConfig = {
type: this.chartType.toLowerCase(),
data: {
labels: transformed.xaxis,
datasets: datasets
},
options: { // Should check whether options are valid before using
title: {
display: this.chartOption_chartTitle,
fontSize: 16,
text: this.chartOption_chartTitleText
},
scales: (this.activeChartDefinition.hasYAxis) ? {
xAxes: [{
scaleLabel: {
display: this.chartOption_xAxisLabel,
labelString: this.chartOption_xAxisLabelText
},
stacked: this.activeChartDefinition.stackable && this.chartOption_stack
}],
yAxes: [{
scaleLabel: {
display: this.chartOption_yAxisLabel,
labelString: this.chartOption_yAxisLabelText
},
stacked: this.activeChartDefinition.stackable && this.chartOption_stack,
ticks: {
beginAtZero: this.chartOption_beginAtZero
}
}]
} : null,
plugins: {
colorschemes: {
scheme: 'tableau.Classic20'
},
zoom: {
pan: {
enabled: (this.activeChartDefinition.hasYAxis && (this.zoomX || this.zoomY)),
mode: '' + (this.zoomX ? 'x' : '') + (this.zoomY ? 'y' : '')
},
zoom: {
enabled: (this.activeChartDefinition.hasYAxis && (this.zoomX || this.zoomY)),
mode: '' + (this.zoomX ? 'x' : '') + (this.zoomY ? 'y' : '')
}
}
}
}
}
if (refreshHtml) {
this.chartId = Math.floor(Math.random() * 10000);
this.html = JSON.stringify(chartConfig);
}
this.chart = new Chart(ctx, chartConfig);
},
/**
* Prepares selected data series for render.
*/
transform() {
let xaxis = [];
const xaxisIndex = 0;
for (let row of this.raw) {
xaxis.push(row[xaxisIndex]);
}
xaxis.shift();
console.log(`Horizontal axis: ${xaxis}`);
let series = [];
/* series is an array storing the data series to be rendered.
* Each element of an array is an object: { seriesName: 'SERIES NAME', data: [ numbers of the series ] }
*/
let seriesIndex = [];
// Find indices from series name, store them into seriesIndex[]
if (Array.isArray(this.selected))
this.selected.map( (seriesName) => seriesIndex.push(this.header.indexOf(seriesName) + 1));
// +1? this.header has the first element stripped. As we will use this index to retrieve the data in this.raw, we need to add back 1.
else
seriesIndex.push(this.header.indexOf(this.selected) + 1);
// Extract data from raw, store them into series[]
seriesIndex.map ( (seriesI) => {
series.push({ seriesName: this.header[seriesI - 1], data: [] }); // -1 to retrieve series name from this.header
if (!this.activeChartDefinition.scatterTransform) {
// Extract data for general charts
this.raw.map( (row) => {
series[series.length - 1].data.push(row[seriesI]);
})
}
else {
// Extract data for scatter charts
this.raw.map( (row, i) => {
series[series.length - 1].data.push({ x: xaxis[i - 1], y: row[seriesI] })
})
}
series[series.length - 1].data.shift();
} );
console.log(series);
return { xaxis, series };
},
/**
* Transposes csv table.
*/
transpose() {
if (!this.completed) return;
this.raw = this.raw[0].map((x,i) => this.raw.map(x => x[i]));
this.header = Array.from(this.raw[0]); // problem: duplicated / null headers
this.header.shift();
this.selected = [];
this.refreshPreview();
},
/**
* Updates the chart options available for the specified chart type.
*
* @param {Boolean} doRender Whether or not chart should be rendered after updating chart options.
* Should be true when chart options are updated by user so that changes can be previewed immediately.
* Should be false during initialization of page when data series are not yet ready.
*/
updateChartType(doRender = true) {
let chartType = this.chartType;
this.activeChartDefinition = this.chartDefinition.find( chart => chart.title === chartType);
console.log(this.activeChartDefinition.title);
if (doRender)
this.render();
},
/**
* Extracts the first 8 cols and 16 rows of the raw csv data for preview under large file mode.
* Should be called after data has changed
*/
refreshPreview() {
this.preview = this.raw.slice(0, 16).map(row => row.slice(0, 8));
console.log(this.preview);
},
/**
* Removes excess columns from the raw csv data.
* Note: Unlike the more efficient row limit provided by PapaParse which does not load excess rows, we need to load all columns before removal.
*
* @param {Number} numCols First numCols columns will be kept.
*/
limitColumns(numCols) {
if (numCols <= 0) return;
this.raw = this.raw.map(row => row.slice(0, numCols));
},
/**
* Returns the number of rows and columns from A1 to the target address.
*
* @param {String} cellAddress Target address for calculation
*/
getNumColsFromA1(cellAddress) {
let col = "";
for (const c of cellAddress) {
if (c.toUpperCase().charCodeAt(0) >= 65 && c.toUpperCase().charCodeAt(0) <= 90)
col += c.toUpperCase();
else
break;
}
let numCols = 0;
for (let i = 0, j = col.length - 1; i < col.length; i++, j--) {
numCols += (col.charCodeAt(j) - 64) * (26 ** i);
}
let numRows = parseInt(cellAddress.replace(/\D/g,''));
return {
col, // The parsed column in alphabets for display
numCols: numCols > 0 ? numCols : 0,
numRows: numRows > 0 ? numRows : 0
}
},
registerTooltips() {
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
}
},
mounted() {
this.updateChartType(false);
}
})
function saveImage() {
let canvas = document.getElementById("csv-chart");
let image = canvas.toDataURL(`image/png`).replace(`image/png`, "image/octet-stream");
window.location.href = image;
}
let canvas = document.getElementById('csv-chart');
canvas.onclick = function(evt) {
let canvas = document.getElementById('csv-chart');
var activePoints = this.chart.getElementsAtEvent(evt);
if (activePoints[0]) {
var chartData = activePoints[0]['_chart'].config.data;
var idx = activePoints[0]['_index'];
var label = chartData.labels[idx];
var value = chartData.datasets[0].data[idx];
alert(value)
console.log(value)
}
};
$(function () {
$('[data-toggle="tooltip"]').tooltip()
})
如果您看到最后一段,您可以找到我一直停留在代码
let canvas = document.getElementById('csv-chart');
canvas.onclick = function(evt) {
let canvas = document.getElementById('csv-chart');
var activePoints = this.chart.getElementsAtEvent(evt);
if (activePoints[0]) {
var chartData = activePoints[0]['_chart'].config.data;
var idx = activePoints[0]['_index'];
var label = chartData.labels[idx];
var value = chartData.datasets[0].data[idx];
alert(value)
console.log(value)
}
};
当我点击图表时,它显示错误为
error : Uncaught TypeError: Cannot read properties of undefined (reading 'getElementsAtEvent') at canvas.onclick (index.js:345:36)
我错过了什么吗?...请帮助我
1条答案
按热度按时间ecfdbz9o1#
您正尝试从文档中获取
getElementsAtEvent
函数,但它不在文档中。您需要在图表示例中调用它,如下所示: