问题,canvas元素可能在哪些场景调整大小?
我试图通过将.toBase64Image()输出发送到服务器来保存Chart.js生成的画布图像,问题是有时图像以不同的大小保存。所以我做的是创建一个单独的隐形画布,没有动画和固定的高度和宽度,甚至考虑到window.devicePixelRatio(这可能使元素调整大小),但元素仍然在一些情况下调整大小,以逃避我的视线:/
相关代码:
var canvas = $('<canvas/>');
canvas[0].width = 680;
canvas[0].height = 480;
// Mobile devices with higher devicePixelRatio would cause Chart.js to resize
// the canvas, temporally modifying window.devicePixelRatio to avoid it.
var originalDevicePixelRatio = window.devicePixelRatio;
window.devicePixelRatio = 0;
window.myRadar = new Chart(canvas[0].getContext("2d")).Radar(radarChartData, {
animation: false,
showscale: false,
scaleShowLabels: false,
showTooltips: false,
scaleLineWidth: 2,
pointLabelFontFamily: "Open Sans",
pointLabelFontColor: "#666",
pointLabelFontSize : 14,
pointLabelFontStyle : "600",
onAnimationComplete: function () {
radar = this;
$.ajax({
type: "POST",
url: submitUrl,
data: {'image': radar.toBase64Image()},
dataType: "json",
success: function(data){
radar.destroy(); // We dont need this radar anymore.
}
});
window.devicePixelRatio = originalDevicePixelRatio;
},
});
我已经阅读了代码,我发现的唯一一件事就是根据window.devicePixelRatio来调整retinaScale()函数。这可以通过强制该值为0来解决。
我在这里尝试实现的是将画布保存为服务器中具有标准尺寸的图像。是否有最佳或推荐的方法来做到这一点?我能想到的就是看不见的画布,也许还有更好的方法......
提前致谢!欢呼声。
答案 0 :(得分:0)
正如您所发现的那样,ChartJS会根据需要调整画布的大小。它可能会改变宽度,高度,两者或两者都不会,因此最终画布的形状是不可预测的。
您可能设置的限制调整大小的一个选项是:
responsive: false,
我想您可以做的最好的事情是将ChartJS画布绘制到另一个具有所需大小的画布。
这是一个函数,可以让您将ChartJS画布绘制到新画布,而不会导致在此过程中裁剪图表。警告 - 可能需要调整的未经测试的代码!
// create a new canvas of a specified size
function resize(chartCanvas,newWidth,newHeight){
var newCanvas=document.createElement('canvas');
var newCtx=newCanvas.getContext('2d');
var cw=newCanvas.width=newWidth;
var ch=newCanvas.height=newHeight;
var iw=chartCanvas.width;
var ih=chartCanvas.height;
var scale=scalePreserveAspectRatio(iw,ih,cw,ch);
newCtx.drawImage(chartCanvas,0,0,iw,ih,0,0,iw*scale,ih*scale);
return(newCanvas);
}
// calculate a scaling factor that preserves
// the original aspect ratio
function scalePreserveAspectRatio(imgW,imgH,maxW,maxH){
return(Math.min((maxW/imgW),(maxH/imgH)));
}