在(Android WebView HTML5 canvas error)我发布了一个关于使用Graph.js库绘制图表的问题。 我现在的问题是,如果我调用函数多次绘制图形,画布每次调整大小。每次将图形重绘为同一画布时,其大小也会发生变化。 我也试过设置画布的大小但没有成功。
可能是什么原因?为什么画布每次调整大小?
答案 0 :(得分:156)
我遇到了很多问题,因为在鼠标悬停之后,我的线条图看起来很糟糕,我找到了一种更简单的方法,希望它会有所帮助:)
使用这些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,
答案 1 :(得分:61)
正在发生的事情是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);
答案 2 :(得分:23)
这对我有用:
<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中设置画布的大小。
答案 3 :(得分:17)
在IOS和Android中,浏览器会在您滚动时隐藏工具栏,从而更改窗口的大小,以便调整图表的大小。 解决方案是保持宽高比。
var options = {
responsive: true,
maintainAspectRatio: true
}
这可以解决您的问题。
答案 4 :(得分: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);
}
答案 5 :(得分:4)
我不得不在这里使用多个答案的组合,并进行一些小调整。
首先,必须将canvas元素包装在块级容器中。我告诉你,不让画布元素有兄弟姐妹;让它成为一个孤独的孩子,因为它是顽固的和被宠坏了。 (包装纸可能不需要任何尺寸限制,但为了安全起见,应用最大高度可能是好的。)
确保满足以前的条件后,在启动图表时,请确保使用以下选项:
var options = {
"responsive": true,
"maintainAspectRatio": false
}
如果要调整图表的高度,请在画布元素级别执行此操作。
<canvas height="500"></canvas>
不要试图以任何其他方式对待孩子。这应该会产生一个令人满意的,布局合理的图表,一个平静地保留在婴儿床中的图表。
答案 6 :(得分: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);
}
如果调用一次就没问题,但是当你多次重绘时,最终会多次改变画布DOM元素的大小,导致重新调整大小。
希望有所帮助!
答案 7 :(得分:1)
如果有人遇到问题,我找到了一个不会牺牲响应性等的解决方案。
只需将画布包装在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
答案 8 :(得分:1)
我尝试使用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);
}
按照我的代码链接:
答案 9 :(得分:0)
我遇到了同样的问题。我可以通过设置选项来解决它:
responsive: false,
maintainAspectRatio: true,
showScale: false,
在CSS中,将容器div的宽度设置为与画布相同:
#canvasContainer {
width: 300px;
}
canvas {
width: 300px;
}
答案 10 :(得分:0)
以下是官方文档: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>
答案 11 :(得分:0)
我在这个线程上尝试了多个答案,对我有用的是(注意我使用的是 reactjs),检查我之前传递到图表组件的道具。 当我调整 DOM 大小时,图表被空数据重新绘制。
componentDidUpdate(prevProps: ChartProps) { if(prevProps.data !== props.data) renderChart(); }
答案 12 :(得分:0)
接受的 - responsive:true, maintainAspectRatio:false
- 不适用于我的场景。
但我发现我们可以简单地调用图表上的 update
方法。
所以我发现自己在调整 matchMedia 侦听器中的值.. 像这样:
myRadarChart.options.scales.r.pointLabels.font.size = "1rem";
myRadarChart.update();
答案 13 :(得分:-2)
添加div
即可解决问题
<div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>
答案 14 :(得分:-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);