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 画布调整大小的主要内容,如果未能解决你的问题,请参考以下文章