You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ChartJS Tooltip显示异常:无法完整展示自定义信息

折线图Tooltip信息缺失排查请求

我尝试为折线图的Tooltip(鼠标悬停数据点时)添加Player Count、Game Time、Game Date三类信息,但目前仅显示Player Count;其中Game Date未在图表中展示,Game Time为X轴。调试时控制台无报错,也未输出任何console.log内容,已确认脚本路径正确(修改折线颜色生效),查阅文档后仍未找到问题,请求同行协助排查错误。

document.addEventListener('DOMContentLoaded', function() {
    var form = document.getElementById('table-form');
    var select = document.getElementById('tables');
    var chartContainer = document.getElementById('line-chart');
    var ctx = chartContainer.getContext('2d');
    var chart;
    var toggleDots = document.getElementById('toggle-dots');

    // Fetch tables from the database
    fetch('fetch_tables.php')
    .then(response => response.json())
    .then(data => {
        data.forEach(function(table) {
            var option = document.createElement('option');
            option.text = table;
            select.add(option);
        });
    });

    // Form submission event listener
    form.addEventListener('submit', function(event) {
        event.preventDefault();
        var selectedTable = select.value;
        console.log('Selected table:', selectedTable); // Log selected table for debugging
        fetchData(selectedTable);
    });

    // Function to fetch data from the selected table
    function fetchData(table) {
        fetch('fetch_data.php?table=' + table)
        .then(response => response.json())
        .then(data => {
            var labels = [];
            var counts = [];
            var gameDates = [];
            var gameTimes = [];

            data.forEach(function(entry) {
                labels.push(entry.GameTime);
                counts.push(Number(entry.PlayerCount)); // Convert PlayerCount to number before pushing
                gameDates.push(entry.GameDate); // Store GameDate
                gameTimes.push(entry.GameTime); // Store GameTime
            });

            console.log('Counts array:', counts); // Log counts array for debugging

            // Calculate statistics
            var maxPlayerCount = Math.max(...counts);
            var minPlayerCount = Math.min(...counts);
            var sumPlayerCount = counts.reduce((acc, curr) => acc + curr, 0);
            var avgPlayerCount = sumPlayerCount / counts.length;

            console.log('Sum of player counts:', sumPlayerCount); // Log sum of player counts
            console.log('Average player count before rounding:', avgPlayerCount); // Log average player count before rounding

            // Ensure the average is rounded to two decimal places
            avgPlayerCount = parseFloat(avgPlayerCount.toFixed(2));

            console.log('Average player count after rounding:', avgPlayerCount); // Log average player count after rounding

            // Update statistics placeholders
            document.getElementById('highest-player-count').textContent = 'Highest Player Count: ' + maxPlayerCount;
            document.getElementById('lowest-player-count').textContent = 'Lowest Player Count: ' + minPlayerCount;
            document.getElementById('average-player-count').textContent = 'Average Player Count: ' + avgPlayerCount;

            // Draw chart
            drawChart(labels, counts, gameDates, gameTimes);
        })
        .catch(error => console.error('Error fetching data:', error)); // Log any errors
    }

    // Function to draw the chart
    function drawChart(labels, counts, gameDates, gameTimes) {
        if (chart) {
            chart.destroy();
        }

        chart = new Chart(ctx, {
            type: 'line',
            data: {
                labels: labels,
                datasets: [{
                    label: 'Player Count',
                    data: counts,
                    backgroundColor: 'rgba(54, 162, 235, 0.2)',
                    borderColor: 'rgba(54, 162, 235, 1)',
                    borderWidth: 1,
                    pointRadius: toggleDots.checked ? 3 : 0,
                    pointHoverRadius: 5
                }]
            },
            options: {
                responsive: true,
                maintainAspectRatio: false,
                scales: {
                    xAxes: [{
                        type: 'time',
                        time: {
                            unit: 'day'
                        },
                        ticks: {
                            autoSkip: true,
                            maxTicksLimit: 10
                        },
                        scaleLabel: {
                            display: true,
                            labelString: 'Game Time'
                        }
                    }],
                    yAxes: [{
                        scaleLabel: {
                            display: true,
                            labelString: 'Player Count'
                        }
                    }]
                },
                tooltips: {
                    callbacks: {
                        title: function(tooltipItem, data) {
                            // Tooltip title will be the Game Date
                            var index = tooltipItem[0].index;
                            var gameDate = gameDates[index];
                            console.log('Tooltip title (Game Date):', gameDate); // Log gameDate
                            return 'Game Date: ' + gameDate;
                        },
                        label: function(tooltipItem, data) {
                            var label = data.datasets[tooltipItem.datasetIndex].label || '';
                            if (label) {
                                label += ': ';
                            }
                            label += tooltipItem.yLabel;
                            console.log('Tooltip label:', label); // Log tooltip label
                            return label;
                        },
                        afterLabel: function(tooltipItem, data) {
                            var index = tooltipItem.index;
                            var gameTime = gameTimes[index];
                            console.log('Tooltip afterLabel (Game Time):', gameTime); // Log gameTime
                            return 'Game Time: ' + gameTime;
                        }
                    }
                }
                
            }
        });
    }

    // Toggle event listener for data points
    toggleDots.addEventListener('change', function() {
        if (chart) {
            chart.data.datasets.forEach(dataset => {
                dataset.pointRadius = this.checked ? 3 : 0;
            });
            chart.update();
        }
    });
});

排查与修复建议

1. 优先确认Chart.js版本兼容性

你的Tooltip回调写法是Chart.js 2.x的规范,如果当前使用的是v3+版本,API结构已变更:

  • tooltips配置需移至plugins.tooltip下
  • 回调函数的参数结构完全不同(比如tooltipItem不再是数组,而是单个上下文对象)
  • 验证版本:打开浏览器控制台输入Chart.version查看

如果是v3+,修改Tooltip配置示例:

options: {
  // ...其他配置
  plugins: {
    tooltip: {
      callbacks: {
        title: function(context) {
          const index = context[0].parsed.x;
          return 'Game Date: ' + gameDates[index];
        },
        label: function(context) {
          let label = context.dataset.label || '';
          if (label) label += ': ';
          label += context.parsed.y;
          return label;
        },
        afterLabel: function(context) {
          const index = context.parsed.x;
          return 'Game Time: ' + gameTimes[index];
        }
      }
    }
  }
}

2. 验证数据有效性

  • 在fetchData函数里添加日志,确认gameDates和gameTimes是否正确获取:
    console.log('Game Dates:', gameDates);
    console.log('Game Times:', gameTimes);
    
  • 检查后端返回的字段名是否和代码匹配(比如后端返回game_date而非GameDate,大小写敏感)

3. 修复控制台日志不输出问题

  • 检查浏览器控制台的日志过滤规则,确认未隐藏Info级日志
  • 确认fetchData函数是否执行:查看网络请求面板,检查fetch_data.php是否发起请求、返回的JSON数据是否正确

4. 确保Tooltip触发正常

临时强制设置pointRadius: 3(不管toggle状态),测试Tooltip是否能触发所有回调——如果pointRadius为0,部分场景下Tooltip触发会不稳定

内容的提问来源于stack exchange,提问作者Fire Aussie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 07:23:16