带有缩放插件的 Chartjs 只用单圈就可以用轮子缩放太多

Chartjs with zoom plugin zooms too much with wheel just with single turn

我有一个带有图表的虚拟网页,但是当我稍微滚动我的滚轮时,我一直放大。我如何限制放大的数量。我尝试在插件->缩放中使用限制选项但是它再次一直放大,之后无法缩小。我使用 chartjs 版本 3.7.1,缩放插件版本 1.2.0,并在 chrome 和边缘浏览器上尝试这个。

//data creation
let ChartDataArray = [];
let labels2 = [];
let data2 = []
i = 0
k = 0

let data3 = [];
data3 = data2;
let labels3 = [];
labels3 = labels2;
const colorset = ["red", "blue", "red"]
let backgroundColorArr = [];
let backgroundColorArr2 = [];



//data creation
while (k < 15000) {
    if (i <= 4999) {
        // let last_hall = 600
        // data2.push(last_hall)
        // labels2.push(k);
        // i++
        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({ x: date, y: 600 });
        i++;
        backgroundColorArr.push(colorset[k % 3]);
    }

    if (i >= 5000) {

        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({ x: date, y: 450 });
        i++;
        backgroundColorArr.push(colorset[k % 3]);
        if (i == 12000) {
            console.log("k: " + k)
            ChartDataArray.push({ x: date, y: 450 });
            ChartDataArray.push({ x: date, y: 450 });
            k += 2;
            console.log("k: " + k)
            for (let j = 0; j < 2000; j++) {
                //let last_hall = getRandomInt(800, 1300)
                // let last_hall = 1000
                // data2.push(last_hall)
                // labels2.push(k);
                let time = Date.now() + k * 1000
                var date = new Date(time)
                ChartDataArray.push({ x: date, y: 1000 });
                backgroundColorArr.push(colorset[k % 3]);
                k++
            }
            console.log("k: " + k)
            for (let j = 0; j < 800; j++) {

                let time = Date.now() + k * 1000
                var date = new Date(time)
                ChartDataArray.push({ x: date, y: 1000 + j });
                backgroundColorArr.push(colorset[k % 3]);
                k++
            }
            console.log("k: " + k)
            for (let j = 0; j < 100; j++) {

                let time = Date.now() + k * 1000
                var date = new Date(time)
                ChartDataArray.push({ x: date, y: 1000 - 2 * j });
                backgroundColorArr.push(colorset[k % 3]);
                k++
            }
            console.log("k: " + k)
            for (let j = 0; j < 100; j++) {

                let time = Date.now() + k * 1000
                var date = new Date(time)
                ChartDataArray.push({ x: date, y: 1000 + j });
                backgroundColorArr.push(colorset[k % 3]);
                k++
            }
            console.log("k: " + k)
            i = 0
        }


    }

    k++
}



var ctx = document.getElementById('myChart2').getContext('2d');
var ctx2 = document.getElementById('myChart3').getContext('2d');


const up = (ctx, value) => ctx.p0.parsed.y >= ctx.p1.parsed.y ? value : undefined;
const down = (ctx, value) => ctx.p0.parsed.y < ctx.p1.parsed.y ? value : undefined;
const up2 = (ctx2, value) => ctx2.p0.parsed.y >= ctx2.p1.parsed.y ? value : undefined;
const down2 = (ctx2, value) => ctx2.p0.parsed.y < ctx2.p1.parsed.y ? value : undefined;




//Decimation

if (ChartDataArray.length > 1000) {
    var datastep = Math.ceil(ChartDataArray.length / 1000) //always show 1000 values from all data
    console.log(datastep);
    for (i = 0; i < 1000; i++) {
        let index = i * datastep
        ChartDataArray[i] = ChartDataArray[index];
        backgroundColorArr[i] = backgroundColorArr[index];
        //labels3[i] = labels3[i * datastep];

    }

}

ChartDataArray = ChartDataArray.slice(0, 937);
backgroundColorArr = backgroundColorArr.slice(0, 937);



console.log("sil: " + ChartDataArray[0]["y"]);
console.log(ChartDataArray);
for (let index = 0; index < ChartDataArray.length - 1; index++) {
    data2[index] = (ChartDataArray[index]["y"]);
}

var chartData = {
    datasets: [{
        label: "values",
        data: ChartDataArray,
        lineTension: 0.1,
        fill: true,
        //backgroundColor: backgroundColorArr[ctx.p0DataIndex],
        segment: {
            borderColor: ctx => backgroundColorArr[ctx.p0DataIndex], //up(ctx, 'rgba(75,192,192,1)') || down(ctx, "red"),
            backgroundColor: ctx => backgroundColorArr[ctx.p0DataIndex]

        },
    }]
};

console.log(ChartDataArray.length)
console.log(backgroundColorArr.length)
console.log(ChartDataArray)
console.log(backgroundColorArr)
console.log()


let chart3 = new Chart(ctx, {
    type: 'line',
    data: chartData,

    options: {


        showLines: false,
        elements: {
            line: {
                tension: 0 // disables bezier curves
            }
        },

        scales: {
            x: {
                type: "time",
                ticks: {
                    maxTicksLimit: 10,

                    //////////////
                    autoSkip: false,
                    suggestedMin: 20,
                    min: 20,
                    sampleSize: 20,
                    autoSkip: false,
                    maxRotation: 20,
                    minRotation: 20
                    /////////////////

                },
               
            },
            y: {

                beginAtZero: true,
                min: Math.min.apply(Math, data2) - 200,
                max: Math.max.apply(Math, data2) + 200
            }

        },

        datasets: {
            parsing: false,
           
            line: {
                pointRadius: 0 // disable for all `'line'` datasets
            }
          
        },
        plugins: {
            // decimation: {
            //     algorithm: 'lttb',
            //     enabled: true,
            //     samples: 20
            // },
            zoom: {
                limits: {
                    y: { min: 0, max: 10 },
                    x: { min: 0, max: 10 }

                },
                // rangeMin: {
                //     x: 10,
                //     y: 200

                // },
                pan: {
                    enabled: true,
                    mode: 'x',
                    speed: 15,
                    threshold: 5,
                    rangeMin: {
                        x: Date.parse((ChartDataArray[0]["x"]))
                    },
                    rangeMax: {
                        y: Math.max.apply(Math, data2)
                    }
                },
                zoom: {
                    limits: {
                        y: { min: -10, max: 1.1 },
                        x: { min: -10, max: 1.1 }

                    },

                    wheel: {
                        enabled: true,
                        speed: 1.0
                    },
                    pinch: {
                        enabled: true
                    },
                    mode: "x",
                    speed: 0.1,
                    threshold: 2,
                    sensitivity: 3,
                }
            },
            afterRender: function (c) {
                console.log("afterRender called");
                var ctx = c.chart.ctx;
                ctx.save();
                // This line is apparently essential to getting the
                // fill to go behind the drawn graph, not on top of it.
                // Technique is taken from:
                // 
                ctx.globalCompositeOperation = 'destination-over';
                ctx.fillStyle = 'white';
                ctx.fillRect(0, 0, c.chart.width, c.chart.height);
                ctx.restore();
            }
        }
    }
});






function resetZoom() {
    chart2.resetZoom();

}

function resetZoom2() {
    chart3.resetZoom();

}
function zoomButton() {
    chart2.zoom(1.1);

}
function zoomButton2() {
    chart3.zoom(1.3);

}
function zoomOutButton() {
    chart2.zoom(0.9);

}
function zoomOutButton2() {
    chart3.zoom(0.7);

}

function getRandomInt(min, max) {
    min = Math.ceil(min);
    max = Math.floor(max);
    return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>Charts, Charts, Charts</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <link rel="stylesheet" type="text/css" href="mystyle.css">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"
        integrity="sha512-UXumZrZNiOwnTcZSHLOfcTs0aos2MzBWHXOHOuB0J/R44QB0dwY5JgfbvljXcklVf65Gc4El6RjZ+lnwd2az2g=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js"
        integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script src="https://cdn.jsdelivr.net/npm/moment@^2"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@^1"></script>
</head>

<body>
    <button onclick="download_csv_file()"> Download CSV </button>
    <h1>Charts, Charts, Charts</h1>
    <div class="container">
        <div class="row">

            <div class="col-6 chart">
                <canvas id="myChart2" width="1000" height="800"></canvas>
                <button onclick="resetZoom2()"> Reset </button>
                <button onclick="zoomOutButton2()"> Zoom Out </button>
                <button onclick="zoomButton2()"> Zoom In</button>
            </div>
        </div>
        <div class="row">
            <div class="col-6 chart">
                <canvas id="myChart3" width="1000" height="800"></canvas>

                <button onclick="resetZoom()"> Reset </button>

                <button onclick="zoomButton()"> Zoom In</button>
                <button onclick="zoomOutButton()"> Zoom Out</button>

            </div>
            <div class="col-6 chart">
                <canvas id="myChart4" width="500" height="400"></canvas>
            </div>
        </div>
    </div>
    <script src="script.js"></script>
</body>

</html>

这是因为您设置的限制和滚动速度。 在您的限制中,您将 x 设置为最大值 10,并将滚动速度设置为默认值的 10 倍。将此设置为默认值并删除 x 轴上的 verry aggresive 限制它工作正常:

//data creation
let ChartDataArray = [];
let labels2 = [];
let data2 = []
i = 0
k = 0

let data3 = [];
data3 = data2;
let labels3 = [];
labels3 = labels2;
const colorset = ["red", "blue", "red"]
let backgroundColorArr = [];
let backgroundColorArr2 = [];



//data creation
while (k < 15000) {
  if (i <= 4999) {
    // let last_hall = 600
    // data2.push(last_hall)
    // labels2.push(k);
    // i++
    let time = Date.now() + k * 1000
    var date = new Date(time)
    ChartDataArray.push({
      x: date,
      y: 600
    });
    i++;
    backgroundColorArr.push(colorset[k % 3]);
  }

  if (i >= 5000) {

    let time = Date.now() + k * 1000
    var date = new Date(time)
    ChartDataArray.push({
      x: date,
      y: 450
    });
    i++;
    backgroundColorArr.push(colorset[k % 3]);
    if (i == 12000) {
      console.log("k: " + k)
      ChartDataArray.push({
        x: date,
        y: 450
      });
      ChartDataArray.push({
        x: date,
        y: 450
      });
      k += 2;
      console.log("k: " + k)
      for (let j = 0; j < 2000; j++) {
        //let last_hall = getRandomInt(800, 1300)
        // let last_hall = 1000
        // data2.push(last_hall)
        // labels2.push(k);
        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({
          x: date,
          y: 1000
        });
        backgroundColorArr.push(colorset[k % 3]);
        k++
      }
      console.log("k: " + k)
      for (let j = 0; j < 800; j++) {

        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({
          x: date,
          y: 1000 + j
        });
        backgroundColorArr.push(colorset[k % 3]);
        k++
      }
      for (let j = 0; j < 100; j++) {

        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({
          x: date,
          y: 1000 - 2 * j
        });
        backgroundColorArr.push(colorset[k % 3]);
        k++
      }
      for (let j = 0; j < 100; j++) {

        let time = Date.now() + k * 1000
        var date = new Date(time)
        ChartDataArray.push({
          x: date,
          y: 1000 + j
        });
        backgroundColorArr.push(colorset[k % 3]);
        k++
      }
      console.log("k: " + k)
      i = 0
    }


  }

  k++
}



var ctx = document.getElementById('myChart2').getContext('2d');
var ctx2 = document.getElementById('myChart3').getContext('2d');


const up = (ctx, value) => ctx.p0.parsed.y >= ctx.p1.parsed.y ? value : undefined;
const down = (ctx, value) => ctx.p0.parsed.y < ctx.p1.parsed.y ? value : undefined;
const up2 = (ctx2, value) => ctx2.p0.parsed.y >= ctx2.p1.parsed.y ? value : undefined;
const down2 = (ctx2, value) => ctx2.p0.parsed.y < ctx2.p1.parsed.y ? value : undefined;




//Decimation

if (ChartDataArray.length > 1000) {
  var datastep = Math.ceil(ChartDataArray.length / 1000) //always show 1000 values from all data
  console.log(datastep);
  for (i = 0; i < 1000; i++) {
    let index = i * datastep
    ChartDataArray[i] = ChartDataArray[index];
    backgroundColorArr[i] = backgroundColorArr[index];
    //labels3[i] = labels3[i * datastep];

  }

}

ChartDataArray = ChartDataArray.slice(0, 937);
backgroundColorArr = backgroundColorArr.slice(0, 937);

for (let index = 0; index < ChartDataArray.length - 1; index++) {
  data2[index] = (ChartDataArray[index]["y"]);
}

var chartData = {
  datasets: [{
    label: "values",
    data: ChartDataArray,
    lineTension: 0.1,
    fill: true,
    //backgroundColor: backgroundColorArr[ctx.p0DataIndex],
    segment: {
      borderColor: ctx => backgroundColorArr[ctx.p0DataIndex], //up(ctx, 'rgba(75,192,192,1)') || down(ctx, "red"),
      backgroundColor: ctx => backgroundColorArr[ctx.p0DataIndex]

    },
  }]
};

let chart3 = new Chart(ctx, {
  type: 'line',
  data: chartData,

  options: {


    showLines: false,
    elements: {
      line: {
        tension: 0 // disables bezier curves
      }
    },

    scales: {
      x: {
        type: "time",
        ticks: {
          maxTicksLimit: 10,

          //////////////
          autoSkip: false,
          suggestedMin: 20,
          min: 20,
          sampleSize: 20,
          autoSkip: false,
          maxRotation: 20,
          minRotation: 20
          /////////////////

        },

      },
      y: {

        beginAtZero: true,
        min: Math.min.apply(Math, data2) - 200,
        max: Math.max.apply(Math, data2) + 200
      }

    },

    datasets: {
      parsing: false,

      line: {
        pointRadius: 0 // disable for all `'line'` datasets
      }

    },
    plugins: {
      // decimation: {
      //     algorithm: 'lttb',
      //     enabled: true,
      //     samples: 20
      // },
      zoom: {
        limits: {
          y: {
            min: 0,
            max: 10
          },

        },
        // rangeMin: {
        //     x: 10,
        //     y: 200

        // },
        pan: {
          enabled: true,
          mode: 'x',
          speed: 15,
          threshold: 5,
          rangeMin: {
            x: Date.parse((ChartDataArray[0]["x"]))
          },
          rangeMax: {
            y: Math.max.apply(Math, data2)
          }
        },
        zoom: {
          wheel: {
            enabled: true,
            speed: 0.1
          },
          pinch: {
            enabled: true
          },
          mode: "x",
          speed: 0.1,
          threshold: 2,
          sensitivity: 3,
        }
      },
      afterRender: function(c) {
        console.log("afterRender called");
        var ctx = c.chart.ctx;
        ctx.save();
        // This line is apparently essential to getting the
        // fill to go behind the drawn graph, not on top of it.
        // Technique is taken from:
        // 
        ctx.globalCompositeOperation = 'destination-over';
        ctx.fillStyle = 'white';
        ctx.fillRect(0, 0, c.chart.width, c.chart.height);
        ctx.restore();
      }
    }
  }
});






function resetZoom() {
  chart2.resetZoom();

}

function resetZoom2() {
  chart3.resetZoom();

}

function zoomButton() {
  chart2.zoom(1.1);

}

function zoomButton2() {
  chart3.zoom(1.3);

}

function zoomOutButton() {
  chart2.zoom(0.9);

}

function zoomOutButton2() {
  chart3.zoom(0.7);

}

function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min) + min); //The maximum is exclusive and the minimum is inclusive
}
<!DOCTYPE html>
<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <title>Charts, Charts, Charts</title>
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" type="text/css" href="mystyle.css">
  <script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js" integrity="sha512-UXumZrZNiOwnTcZSHLOfcTs0aos2MzBWHXOHOuB0J/R44QB0dwY5JgfbvljXcklVf65Gc4El6RjZ+lnwd2az2g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/1.2.0/chartjs-plugin-zoom.min.js" integrity="sha512-TT0wAMqqtjXVzpc48sI0G84rBP+oTkBZPgeRYIOVRGUdwJsyS3WPipsNh///ay2LJ+onCM23tipnz6EvEy2/UA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  <script src="https://cdn.jsdelivr.net/npm/moment@^2"></script>
  <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@^1"></script>
</head>

<body>
  <button onclick="download_csv_file()"> Download CSV </button>
  <h1>Charts, Charts, Charts</h1>
  <div class="container">
    <div class="row">

      <div class="col-6 chart">
        <canvas id="myChart2" width="1000" height="800"></canvas>
        <button onclick="resetZoom2()"> Reset </button>
        <button onclick="zoomOutButton2()"> Zoom Out </button>
        <button onclick="zoomButton2()"> Zoom In</button>
      </div>
    </div>
    <div class="row">
      <div class="col-6 chart">
        <canvas id="myChart3" width="1000" height="800"></canvas>

        <button onclick="resetZoom()"> Reset </button>

        <button onclick="zoomButton()"> Zoom In</button>
        <button onclick="zoomOutButton()"> Zoom Out</button>

      </div>
      <div class="col-6 chart">
        <canvas id="myChart4" width="500" height="400"></canvas>
      </div>
    </div>
  </div>
  <script src="script.js"></script>
</body>

</html>