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

Chart.js Zoom插件在触控设备无法双指缩放的问题求解

解决Chart.js Zoom插件触控设备双指缩放失效问题

你的代码里有几个关键问题导致触控双指缩放功能失效,下面是具体的修复方案:

问题分析

  • 重复引入Chart.js:同时加载了2.9.3和最新版本,导致库冲突,Zoom插件无法正常绑定触控事件
  • Zoom插件触控配置缺失:默认配置未明确启用双指缩放动作,需要手动指定
  • Chart.js版本配置不匹配:原代码中使用了v3+的scales.y配置写法,但实际引入的是v2.x版本,会导致图表渲染异常
  • 响应式关闭影响触控识别:responsive: false让canvas固定尺寸,触控事件的坐标计算容易出现偏差

修复步骤

  1. 移除重复依赖:只保留一个与Zoom插件兼容的Chart.js版本
  2. 完善Zoom触控配置:明确启用双指缩放(pinch)动作,设置合理触发阈值
  3. 修正Chart.js v2.x配置:将scales.y改为v2.x支持的scales.yAxes写法
  4. 开启响应式:让Chart.js自动适配屏幕尺寸,提升触控设备的交互体验
  5. 添加错误处理:避免数据请求失败导致页面卡死

修改后的完整代码

<html>
<head>
  <!-- 保留与Zoom插件兼容的Chart.js 2.9.3版本 -->
  <script src="https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js"></script>
  <!-- Hammer.js是触控事件的必要依赖 -->
  <script src="https://cdn.jsdelivr.net/npm/hammerjs@2.0.8"></script>
  <!-- 对应Chart.js 2.x的Zoom插件版本 -->
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@0.7.7/dist/chartjs-plugin-zoom.min.js"></script>
</head>
<body>
  <div id="loader" style="display: flex; justify-content: center; align-items: center; height: 400px; background-color: #f2f2f2">
    <div style="text-align: center; font-size: 2em; font-weight: bold; color: #3e95cd;">Loading...</div>
  </div>
  <!-- 移除固定尺寸,由Chart.js响应式处理 -->
  <canvas id="myChart" style="display: none; height: 400px;"></canvas>
  <script>
    const ctx = document.getElementById('myChart').getContext('2d');
    // 提取数据URL为常量,避免重复编写
    const DATA_SOURCE_URL = 'https://script.googleusercontent.com/macros/echo?user_content_key=r9CiwwP04Rh83CglKNwLbJw3zKlvAIWVj4Yf9a5cT3CPRmlxaBB9bOAMnkFV2os4ee10iaj9S7HNOU5axJWhdXmuYbHPVyWnm5_BxDlH2jW0nuo2oDemN9CCS2h10ox_1xSncGQajx_ryfhECjZEnC4mxGG_R4juVl897H-HHcU5jBSu36oRyKZzBJteCuzXZ2p8eeHkRfjTV-mrMKhBOgim2y6bAoCZpSiZg9-Rh7EUjhE06fNngtz9Jw9Md8uu&lib=MQ0aMrcKwzFLX_7mD1gjcTxV-kV6j6m2N';

    // 封装数据请求函数
    function getChartData() {
      return fetch(DATA_SOURCE_URL)
        .then(res => {
          if (!res.ok) throw new Error('数据请求失败');
          return res.json();
        });
    }

    // 初始化图表
    getChartData()
      .then(data => {
        document.getElementById("loader").style.display = "none";
        document.getElementById("myChart").style.display = "block";

        const chartData = {
          labels: data.map(d => d.TimeCOI).reverse(),
          datasets: [
            {
              label: 'Nifty PCR COI',
              data: data.map(d => d.Nifty_PCR_COI).reverse(),
              borderColor: '#3e95cd',
              fill: false,
              lineTension: .3,
              pointRadius: 2,
              pointBackgroundColor: '#3e95cd'
            },{
              label: 'Bank Nifty PCR COI',
              data: data.map(d => d.Bank_Nifty_PCR_COI).reverse(),
              borderColor: '#c65e3e',
              fill: false,
              lineTension: .3,
              pointRadius: 2,
              pointBackgroundColor: '#c65e3e'
            }
          ]
        };

        const chartOptions = {
          responsive: true,
          maintainAspectRatio: false,
          zoom: {
            enabled: true,
            mode: 'x',
            drag: true,
            speed: 0.05,
            // 配置触控双指缩放
            touch: {
              enabled: true,
              pinch: true, // 明确启用双指缩放
              threshold: 10 // 触发缩放的最小触控距离,可按需调整
            },
            // 限制缩放范围,防止过度缩放
            limits: {
              x: {min: 'original', max: 'original'}
            }
          },
          scales: {
            // 修正为Chart.js 2.x的y轴配置写法
            yAxes: [{
              beginAtZero: true,
              position: 'right'
            }]
          }
        };

        const chart = new Chart(ctx, {
          type: 'line',
          data: chartData,
          options: chartOptions
        });

        // 定时更新图表
        setInterval(() => {
          getChartData()
            .then(newData => {
              chart.data.labels = newData.map(d => d.TimeCOI).reverse();
              chart.data.datasets[0].data = newData.map(d => d.Nifty_PCR_COI).reverse();
              chart.data.datasets[1].data = newData.map(d => d.Bank_Nifty_PCR_COI).reverse();
              chart.update();
            })
            .catch(err => console.error('更新数据失败:', err));
        }, 1000);
      })
      .catch(err => {
        console.error('初始化图表失败:', err);
        document.getElementById("loader").innerHTML = '<div style="text-align: center; font-size: 1.5em; color: #cd3e3e;">加载失败,请刷新页面</div>';
      });
  </script>
</body>
</html>

关键修改说明

  • 移除了重复的Chart.js引入,解决版本冲突问题
  • 添加了touch配置节点,明确启用双指缩放动作
  • 修正了Chart.js v2.x的y轴配置写法,保证图表正常渲染
  • 开启响应式并添加错误处理,提升页面稳定性和触控体验

内容的提问来源于stack exchange,提问作者MOHD ALI KHAN

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 05:05:20