Chart.js 画布调整大小

Posted

技术标签:

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

在 (android WebView html5 canvas error) 我发布了一个关于使用 Graph.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 ></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);

【讨论】:

以上是关于Chart.js 画布调整大小的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Chart.js 2.9.3 中绘制具有动态厚度的水平条(在浏览器窗口高度调整大小时自动调整大小)?

在窗口调整大小时动态调整画布大小

调整图像大小并使其适合画布大小

Three.js 调整画布大小

画布图像大小调整使文件更大[重复]

将画布大小调整为窗口/用户控件大小