Chartjs:设置拖动时缩放的最小值和适当的用户反馈

stszievb  于 2023-01-20  发布在  Chart.js
关注(0)|答案(1)|浏览(196)

我正在使用Chartjs 4.0.1和chartjs-plugin-zoom 2.0.0,我的图表看起来像这样:

我已经将拖动选项设置为启用,以便用户可以绘制一个矩形来进行放大。我还将缩放模式设置为“x”。因此,用户只能在x轴上进行放大,而不能在y轴上进行放大。现在,我想限制用户可以放大的范围。到一个月的时间跨度。我已经设法做到这一点时,使用鼠标滚轮放大。但我不知道如何实现同样的使用拖动选项。我将其配置为:

  1. drag:{
  2. enabled: true,
  3. backgroundColor:'rgba(180,180,180,0.4)',
  4. threshold: 25,
  5. }

阈值似乎是我最好的选择。然而,它是以像素为单位的,它只说明了绘制的矩形必须有多宽才能发生缩放。我已经使用onZoomStart回调函数来检查图表放大了多远,并基于此决定用户是否可以放大更多。但显然,该回调函数只在通过鼠标滚轮缩放时执行,而在拖动时不执行。所以我想我需要能够动态地设置拖动对象的阈值,有人知道怎么做吗?
我还想知道,是否有可能改变边界颜色的矩形时,拖动显示用户,如果它是足够大的滚动发生?

sy5wg1nm

sy5wg1nm1#

标准的解决方案似乎是设置一个limits:{x:{minRange:...}}选项。我花了一段时间才意识到应该在哪里插入这个选项。
下面是一个代码片段,其中包含一些类似于您的数据,并且minRange设置为90天(因此我可以跳过调整tick间隔)。
此外,如果间隔小于90天,还有一个将拖动矩形的颜色更改为红色的黑客。它可以很容易地适应小于所需间隔时完全拒绝缩放,而不是当前的标准行为,即调整(扩展)间隔,直到它等于minRange
this fiddle中相同。

  1. const nPoints = 400,
  2. t0 = Date.parse("2018-06-02T00:00:00Z"),
  3. dt = 2.5*365/nPoints*24*3600*1000;
  4. const data = Array.from(
  5. {length: nPoints},
  6. (_, i)=>({
  7. "timestamp":(t0+dt*i),
  8. value: 80*Math.sin(i*Math.PI/nPoints)+2*Math.random()
  9. })
  10. );
  11. let mouseMoveHandler = null;
  12. chart = new Chart(document.getElementById("myChart"), {
  13. type: 'line',
  14. data: {
  15. datasets: [{
  16. label: "Count",
  17. //pointStyle: false,
  18. pointRadius: 2,
  19. showLine: true,
  20. fill: true,
  21. tension: 0,
  22. borderColor: '#aa6577',
  23. //pointRadius: 4,
  24. //pointBorderWidth: 1,
  25. //pointBackgroundColor: '#7265ce',
  26. data: data
  27. }]
  28. },
  29. options: {
  30. parsing: {
  31. xAxisKey: 'timestamp',
  32. yAxisKey: 'value'
  33. },
  34. spanGaps: false,
  35. responsive: false,
  36. scales: {
  37. x: {
  38. bounds: 'ticks',
  39. type: 'time',
  40. time: {
  41. unit: 'month',
  42. },
  43. title: {
  44. display: false,
  45. text: 'time'
  46. },
  47. ticks: {
  48. display: true,
  49. color: '#cecece'
  50. }
  51. },
  52. y: {
  53. type: 'linear',
  54. display: true,
  55. min: -10,
  56. max: 140,
  57. ticks: {
  58. autoSkip: true,
  59. color: '#cecece'
  60. },
  61. grid:{
  62. color: ctx => ctx.tick.value === 0 ? '#000' : '#ddd',
  63. lineWidth: ctx => ctx.tick.value === 0 ? 3 : 1,
  64. },
  65. title: {
  66. display: false,
  67. text: 'Count',
  68. align: 'end'
  69. },
  70. }
  71. },
  72. plugins:{
  73. legend:{
  74. display: false
  75. },
  76. zoom: {
  77. zoom: {
  78. drag: {
  79. enabled: true,
  80. backgroundColor:'rgba(180,180,180,0.4)',
  81. },
  82. mode: 'x',
  83. onZoomStart({chart, event}){
  84. const x0 = chart.scales.x.getValueForPixel(event.clientX);
  85. if(event.type==="mousedown"){
  86. mouseMoveHandler = function(e){
  87. if(
  88. Math.abs(chart.scales.x.getValueForPixel(e.clientX) - x0) <
  89. chart.options.plugins.zoom.limits.x.minRange
  90. ){
  91. chart.options.plugins.zoom.zoom.drag.backgroundColor = 'rgba(255,180,180,0.4)';
  92. }
  93. else{
  94. chart.options.plugins.zoom.zoom.drag.backgroundColor = 'rgba(180,180,180,0.4)';
  95. }
  96. };
  97. chart.canvas.addEventListener("mousemove", mouseMoveHandler);
  98. chart.canvas.addEventListener("mouseup", function(){
  99. if(mouseMoveHandler){
  100. chart.canvas.removeEventListener("mousemove", mouseMoveHandler);
  101. mouseMoveHandler = null;
  102. }
  103. }, {once: true});
  104. }
  105. },
  106. onZoomComplete({chart}){
  107. if(mouseMoveHandler){
  108. chart.canvas.removeEventListener("mousemove", mouseMoveHandler);
  109. mouseMoveHandler = null;
  110. }
  111. document.querySelector('#zoom').innerText = chart.getZoomLevel().toFixed(1)+'x';
  112. document.querySelector('#xSpan').innerText =
  113. Math.round((chart.scales.x.max-chart.scales.x.min)/24/3600/1000)+'days';
  114. }
  115. },
  116. limits:{
  117. x: {
  118. minRange: 90 * 24* 3600 * 1000
  119. }
  120. }
  121. }
  122. }
  123. }
  124. });
  125. document.querySelector('#resetZoom').addEventListener('click', function(){chart.resetZoom();});
  126. document.querySelector('#xSpan').innerText = Math.round((chart.scales.x.max-chart.scales.x.min)/24/3600/1000)+'days';
  1. <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.0.1/chart.umd.min.js"
  2. integrity="sha512-HyprZz2W40JOnIBIXDYHCFlkSscDdYaNe2FYl34g1DOmE9J+zEPoT4HHHZ2b3+milFBtiKVWb4sorDVVp+iuqA=="
  3. crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  4. <script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-zoom/2.0.0/chartjs-plugin-zoom.min.js"
  5. integrity="sha512-B6F98QATBNaDHSE7uANGo5h0mU6fhKCUD+SPAY7KZDxE8QgZw9rewDtNiu3mbbutYDWOKT3SPYD8qDBpG2QnEg=="
  6. crossorigin="anonymous" referrerpolicy="no-referrer"></script>
  7. <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js">
  8. </script>
  9. <canvas id="myChart" style="height:500px; width: 90vw"></canvas>
  10. <button id="resetZoom">Reset zoom</button> <br>
  11. zoom: <span id="zoom">1x</span><br>
  12. X axis span: <span id="xSpan"></span>
展开查看全部

相关问题