Chart.js画布调整大小


86

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

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


现在,他们是Chart.js官方网站上专用页面,网址为:chartjs.org/docs/latest/general/sensitive.html测试了该解决方案,效果很好。
阿明27

Answers:


175

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

使用以下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.sensitive = false *
sghosh968 '16

13
不要忘记,要使此方法正常工作,您需要将画布放置在中,<div>并在<div>而不是画布上设置高度和/或宽度。
totymedli

2
这些标志现在默认设置为true,所以你不必摸他们chartjs.org/docs/latest/general/responsive.html
若奥·皮门特尔·费雷拉

与此同时,还设置画布的宽度和高度。然后工作正常。谢谢
Mazhar MIK

63

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

问题是它还没有意识到自己已经做到了,所以当连续调用时,它将已经(再加倍)的大小再乘以一倍,直到事情开始崩溃为止。(实际上,正在通过更改宽度和高度的DOM属性来检查是否应在画布上添加更多像素,如果需要,将其乘以某个因子,通常为2,然后对其进行更改,然后更改css样式属性以保持页面上的相同大小。)

例如,当您运行一次并且将画布的宽度和高度设置为300时,将其设置为600,然后将style属性更改为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);

我遇到了这个错误:未捕获的ReferenceError:未定义
doughnutData

11
呃。是的,那只是一个占位符变量,因为我根本不知道您要绘制的数据是什么。
jcmiller11 '16

26

这对我有用:

<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标签中设置画布的大小。


同意!只需将画布放在div内,然后确保“ response”的选项不是false(默认情况下为true)。然后只需将大小调整规则应用于div。
NoelB

20

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

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

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


6

正如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); 
}

抱歉,您能解释一下这是如何工作的吗?例如,我打开一个页面,然后画布具有一种尺寸,但是如果我调整窗口的大小,画布将具有不同的尺寸(并且我不需要原始尺寸,因为它是用于窗口的先前尺寸的)?
kiradotee '16

6

在这里,我不得不使用多个答案的结合以及一些小的调整。

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

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

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

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

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

不要试图以任何其他方式对待孩子。这样就可以产生一张令人满意的,布局合理的图表,一张和平地放在婴儿床里的图表。


3

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

看起来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);
}

如果只调用一次,这很好,但是当您多次重绘时,最终会多次更改canvas DOM元素的大小,从而导致重新调整大小。

希望有帮助!


1

如果有人遇到问题,我发现了不牺牲响应度等的解决方案。

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

例:

HTML:

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

JS:

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

1

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

以下来自其他Codepan链接的悬停选项:

.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


1

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

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

然后在CSS中,将容器div的宽度设置为与画布相同:

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


0

我在使用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"]

资料来源:mikebarr58


-3

添加div,它将解决问题

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

-5
 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);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.