Chart.js折线图从Firestore取数据后Y轴数据点定位异常
问题:Firestore数据在Chart.js折线图Y轴定位错误,但Tooltip显示正常
从Firestore获取的数据在Chart.js折线图中Y轴定位异常——例如某数据实际值为23,却被渲染到100+的位置,但Tooltip显示的数值是正确的。手动输入数据时,数据点定位完全正常。已确认获取后的数据类型为number,仍无法定位问题原因。

相关代码
<script> import { auth, db } from "../../src/main"; import Sidebar from "../components/Navigation/Sidebar.vue"; import Topbar from "../components/Navigation/Topbar.vue"; import ChartTest from "../components/ProgressPage/ChartTest.vue"; import Chart from 'chart.js/auto'; import { getFirestore, doc, updateDoc, getDoc, setDoc, collection, addDoc, deleteDoc, deleteField, arrayUnion, arrayRemove } from "firebase/firestore"; export default { name: "Progress", components: { Sidebar, Topbar, ChartTest }, mounted() { const progressChart = new Chart(document.getElementById("progress-chart"), { type: 'line', data: { labels: ['CA1', 'SA1', 'CA2', 'SA2'], datasets: [] }, options: { plugins: { title: { display: true, text: this.title } }, scales: { y: { display: true, stacked: true, title: { display: true, text: 'Your Score (%)' } } } } }); this.getData().then((data) => { progressChart.data.datasets = data console.log(typeof(data[0].data[0])) // 输出number this.getCount(data) progressChart.update() }) }, methods: { getCount(data) { this.count = data.length }, async getData() { var email = localStorage.getItem("email"); var ref = doc(db, 'users', email); const docSnap = await getDoc(ref) if (docSnap.exists()) { var data = docSnap.data().progressResults return data } else { console.log('does not exist') } }, async addResult() { let count = this.existingSubjects.length var email = localStorage.getItem("email"); var ref = doc(db, 'users', email); if (!this.existingSubjects.includes(this.subject)) { this.existingSubjects.push(this.subject) const newData = { data: [{ x: this.examType,y:this.score}], label: this.subject, borderColor: this.colors[this.count], fill: false } await updateDoc( ref, { progressResults: arrayUnion(newData) } ) console.log(newData) } else { // 待实现 } } }, data() { return { score: '', examType: '', subject: '', count:0, existingSubjects: [], colors: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850","#21c095","#bbc021","#1a993a","##904b23","#a01359","#a04913","#534270"], title: '', data: { labels: ['CA1', 'SA1', 'CA2', 'SA2'], datasets: [] }, tabs: [{ link: '', name: "subject", dropdown: true, dropdownTabs: [{ name: 'math', link: '#', }, { name: 'science', link: '#', }, ] }, { link: '#', name: "test", dropdown: false, dropdownTabs: [] }, ] } } } </script>
问题原因及解决办法
核心原因:Y轴堆叠模式导致数值累加
你的Chart配置中Y轴开启了stacked: true,但数据结构是每个dataset仅包含单个{x,y}数据点(比如数学科目只有CA1的分数)。堆叠模式会将所有dataset在同一X轴位置的Y值累加,导致单个数据点被“推”到很高的位置——而Tooltip显示的是原始数据值,所以看起来正常。
解决步骤
关闭Y轴堆叠
修改Chart配置中Y轴的stacked属性为false,因为你的场景是展示不同科目在各考试的独立分数,不需要堆叠:scales: { y: { display: true, stacked: false, // 此处修改为false title: { display: true, text: 'Your Score (%)' } } }统一数据格式(可选)
如果手动输入数据时使用的是纯Y值数组(如data: [23, null, null, null]),建议将Firestore获取的数据转换为对应格式,确保和手动输入的结构一致:async getData() { var email = localStorage.getItem("email"); var ref = doc(db, 'users', email); const docSnap = await getDoc(ref) if (docSnap.exists()) { const labels = ['CA1', 'SA1', 'CA2', 'SA2']; return docSnap.data().progressResults.map(dataset => { // 转换为对应labels顺序的Y值数组,不存在的考试填null const dataArray = labels.map(label => { const point = dataset.data.find(p => p.x === label); return point ? Number(point.y) : null; }); return { ...dataset, data: dataArray }; }); } else { console.log('does not exist') } }强制确保数据类型为Number
虽然你已确认数据类型为number,但可以在获取数据时再强制转换一次,避免潜在的类型问题:async getData() { var email = localStorage.getItem("email"); var ref = doc(db, 'users', email); const docSnap = await getDoc(ref) if (docSnap.exists()) { return docSnap.data().progressResults.map(dataset => ({ ...dataset, data: dataset.data.map(point => ({ x: point.x, y: Number(point.y) // 强制转换为Number })) })); } else { console.log('does not exist') } }
内容的提问来源于stack exchange,提问作者user121443
相关产品推荐
相关产品推荐

