【问题标题】:Chart.js canvas resizeChart.js 画布调整大小
【发布时间】:2013-11-19 18:51:16
【问题描述】:

在 (Android WebView HTML5 canvas error) 我发布了一个关于使用 Graph.js 库绘制图表的问题。 我现在遇到的问题是,如果我多次调用该函数来绘制图形,则画布每次都会调整大小。每次将图形重新绘制到同一画布上时,其大小也会发生变化。 我也尝试设置画布的大小,但没有成功。

可能是什么原因?为什么画布每次都会调整大小?

【问题讨论】:

    标签: html canvas chart.js


    【解决方案1】:

    我有很多问题,因为毕竟我的线条图在鼠标悬停时看起来很糟糕,我找到了一种更简单的方法,希望它会有所帮助:)

    使用这些 Chart.js 选项:

    // Boolean - whether or not the chart should be responsive and resize when the browser does.
    
    responsive: true,
    
    // Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container
    
    maintainAspectRatio: false,
    

    【讨论】:

    • 感谢@NoFlag 的回答。对我来说,高度和宽度属性没有被应用到画布上,以防有人最终在这里寻找尝试调整画布大小的解决方案,尝试设置响应为 true。 *Chart.defaults.global.responsive = false *
    • 不要忘记,要使此方法正常工作,您需要将画布放在<div> 中,并在上述<div> 而不是画布上设置高度和/或宽度。
    • 这些标志现在默认设置为true,因此您无需触摸它们:chartjs.org/docs/latest/general/responsive.html
    • 除此之外,还要设置画布的宽度和高度。然后它工作正常。谢谢
    • 就我而言,调用图表的更新方法效果更好;由于其他原因,我不得不关闭响应,所以不能使用这个很好的解决方案。 +1 +alt:answer :-)
    【解决方案2】:

    发生的情况是 Chart.js 在调用时将画布的大小乘以,然后尝试使用 CSS 将其缩小,目的是为高 dpi 设备提供更高分辨率的图形。

    问题是它没有意识到它已经这样做了,所以当连续调用时,它会再次乘以已经(加倍或其他)大小,直到事情开始破裂。 (实际发生的是检查是否应该通过更改宽度和高度的 DOM 属性来向画布添加更多像素,如果应该,将其乘以某个因子,通常为 2,然后更改它,然后更改 css 样式属性以在页面上保持相同的大小。)

    例如,当你运行一次并且你的画布宽度和高度设置为 300 时,它会将它们设置为 600,然后将样式属性更改为 300...但是如果你再次运行它,它会看到 DOM宽度和高度为 600(查看此问题的其他答案以了解原因),然后将其设置为 1200,并将 css 宽度和高度设置为 600。

    不是最优雅的解决方案,但我解决了这个问题,同时通过在每次连续调用 Chart.js 之前手动设置画布的宽度和高度来保持视网膜设备的增强分辨率

    var ctx = document.getElementById("canvas").getContext("2d");
    ctx.canvas.width = 300;
    ctx.canvas.height = 300;
    var myDoughnut = new Chart(ctx).Doughnut(doughnutData);
    

    【讨论】:

    • 我遇到了这个错误:Uncaught ReferenceError: donutData is not defined
    • 错误。是的,这只是一个占位符变量,因为我根本不知道您要绘制什么数据。
    【解决方案3】:

    这对我有用:

    <body>
        <form>
            [...]
            <div style="position:absolute; top:60px; left:10px; width:500px; height:500px;">
                <canvas id="cv_values"></canvas>
    
                <script type="text/javascript">
                    var indicatedValueData = {
                        labels: ["1", "2", "3"],
                        datasets: [
                            {
                                [...]
                            };
    
                    var cv_values = document.getElementById("cv_values").getContext("2d");
                    var myChart = new Chart(cv_values, { type: "line", data: indicatedValueData });
                </script>
            </div>
        </form>
    </body>
    

    基本事实是我们必须在 div-tag 中设置画布的大小。

    【讨论】:

    • 同意!只需将画布放在 div 中,然后确保“响应式”选项不为假(默认情况下为真)。然后只需将大小规则应用于 div。
    【解决方案4】:

    在 IOS 和 Android 中,浏览器在滚动时会隐藏工具栏,从而改变窗口的大小,从而导致 chartjs 调整图形的大小。 解决方法是保持纵横比。

    var options = { 
        responsive: true,
        maintainAspectRatio: true
    }
    

    这应该可以解决您的问题。

    【讨论】:

      【解决方案5】:

      正如 jcmiller11 所建议的,设置宽度和高度会有所帮助。 一个更好的解决方案是在绘制图表之前检索画布的宽度和高度。 然后使用这些数字在每次重新绘制图表时设置图表。 这样可以确保 javascript 代码中没有常量。

      ctx.canvas.originalwidth = ctx.canvas.width;
      ctx.canvas.originalheight = ctx.canvas.height;
      
      function drawchart() {
          ctx.canvas.width = ctx.canvas.originalwidth;
          ctx.canvas.height = ctx.canvas.originalheight;
      
          var chartctx = new Chart(ctx);
          myNewBarChart = chartctx.Bar(data, chartSettings); 
      }
      

      【讨论】:

      • 抱歉,您能解释一下这是如何工作的吗?例如,我打开一个页面,然后画布具有一个大小,但是如果我调整窗口大小,画布将具有不同的大小(大概我不需要原始大小,因为它是窗口的先前大小)?
      【解决方案6】:

      我不得不在这里使用多个答案的组合并进行一些小的调整。

      首先,有必要将画布元素包装在块级容器中。我对你说,不要让canvas元素有兄弟姐妹;让它成为一个孤独的孩子,因为它是固执被宠坏的。 (包装器可能不需要对其施加任何尺寸限制,但为了安全起见,最好对其应用最大高度。)

      在确保满足上述条件后,在启动图表时,请确保使用以下选项:

      var options = { 
          "responsive": true,
          "maintainAspectRatio": false
      }
      

      如果要调整图表的高度,请在画布元素级别进行。

      <canvas height="500"></canvas>
      

      不要试图以任何其他方式与孩子打交道。这应该会产生一个令人满意的、布局合理的图表,一个安静地留在婴儿床里的图表。

      【讨论】:

        【解决方案7】:

        我遇到了类似的问题并找到了您的答案。我最终找到了解决方案。

        看起来 Chart.js 的源代码如下(大概是因为它不应该在同一个画布中重新渲染和完全不同的图形):

            //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
        if (window.devicePixelRatio) {
            context.canvas.style.width = width + "px";
            context.canvas.style.height = height + "px";
            context.canvas.height = height * window.devicePixelRatio;
            context.canvas.width = width * window.devicePixelRatio;
            context.scale(window.devicePixelRatio, window.devicePixelRatio);
        }
        

        如果调用一次就可以了,但是当你多次重绘时,你最终会多次更改画布 DOM 元素的大小,从而导致重新调整大小。

        希望有帮助!

        【讨论】:

          【解决方案8】:

          我遇到了同样的问题。我可以通过设置选项来解决它:

          responsive: false,
          maintainAspectRatio: true,
          showScale: false,

          并且在css中,设置容器div的宽度和canvas一样:

              #canvasContainer { 
                width: 300px;
              }
              
              canvas {
                width: 300px;
              }

          【讨论】:

            【解决方案9】:

            如果有人遇到问题,我找到了一个不涉及牺牲响应能力等的解决方案。

            只需将画布包装在 div 容器中(无样式),然后在调用 Chart 构造函数之前将 div 的内容重置为带有 ID 的空画布。

            例子:

            HTML:

            <div id="chartContainer">
                <canvas id="myChart"></canvas>
            </div>
            

            JS:

            $("#chartContainer").html('<canvas id="myChart"></canvas>');
            //call new Chart() as usual
            

            【讨论】:

              【解决方案10】:

              我尝试使用 jQuery 调整画布大小,但效果不佳。我认为 CSS3 是您可以尝试的最佳选择,如果您想在某个级别进行悬停缩放。

              跟随其他代码盘链接的悬停选项:

              .style_prevu_kit:hover{
                  z-index: 2;
                  -webkit-transition: all 200ms ease-in;
                  -webkit-transform: scale(1.5);
                  -ms-transition: all 200ms ease-in;
                  -ms-transform: scale(1.5);   
                  -moz-transition: all 200ms ease-in;
                  -moz-transform: scale(1.5);
                  transition: all 200ms ease-in;
                  transform: scale(1.5);
              }
              

              关注我的代码盘链接:

              https://codepen.io/hitman0775/pen/XZZzqN

              【讨论】:

                【解决方案11】:

                我在使用 Angular CLI 时遇到了同样的缩放问题。能够通过从 index.html 中删除这一行来使其工作:

                <script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>
                

                然后在 angular-cli.json 文件的脚本部分中,使用:

                "scripts": ["../node_modules/chart.js/dist/Chart.bundle.min.js"]
                

                Source: 迈克巴尔58

                【讨论】:

                  【解决方案12】:

                  这里是官方文档:https://www.chartjs.org/docs/latest/general/responsive.html

                  无法直接从画布元素检测画布大小何时发生变化。 Chart.js 使用其父容器来更新画布渲染和显示大小。但是,此方法要求容器相对定位并仅专用于图表画布。然后可以通过设置容器大小的相对值来实现响应性(示例):

                  <div class="chart-container" style="position: relative; height:40vh; width:80vw">
                      <canvas id="chart"></canvas>
                  </div>
                  

                  【讨论】:

                    【解决方案13】:

                    我在这个线程上尝试了多个答案,对我有用的是(注意我使用的是 reactjs),检查我之前传递给图表组件的道具。 当我调整 DOM 的大小时,图表正在用空数据重新绘制。

                    componentDidUpdate(prevProps: ChartProps) { if(prevProps.data !== props.data) renderChart(); }
                    

                    【讨论】:

                      【解决方案14】:

                      接受的 - responsive:true, maintainAspectRatio:false - 不适用于我的场景。 但我发现我们可以简单地调用图表上的update 方法。

                      所以我发现自己在 matchMedia 侦听器中调整值.. 像这样:

                      myRadarChart.options.scales.r.pointLabels.font.size = "1rem";
                      myRadarChart.update();
                      

                      【讨论】:

                        【解决方案15】:

                        添加div即可解决问题

                        <div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>
                        

                        【讨论】:

                          【解决方案16】:
                           let canvasBox = ReactDOM.findDOMNode(this.refs.canvasBox);
                           let width = canvasBox.clientWidth;
                           let height = canvasBox.clientHeight;
                           let charts = ReactDOM.findDOMNode(this.refs.charts);
                           let ctx = charts.getContext('2d');
                           ctx.canvas.width = width;
                           ctx.canvas.height = height;
                           this.myChart = new Chart(ctx);
                          

                          【讨论】:

                            猜你喜欢
                            • 2023-03-18
                            • 1970-01-01
                            • 1970-01-01
                            • 2013-10-06
                            • 2011-03-14
                            • 2013-12-15
                            • 2014-11-04
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多