Canvas 调整chart.js画布的大小以进行打印
我正在使用Canvas 调整chart.js画布的大小以进行打印,canvas,chart.js,Canvas,Chart.js,我正在使用@media print{自定义我的打印视图。我的图表的问题是,它们的打印大小取决于浏览器窗口的大小。因此,当我的浏览器很大时,画布对于页面来说会太大(我正在使用响应图表) 我试图在@media print{中重新定义画布的大小,但没有成功 当我打印时(不影响我的浏览器视图),有哪些解决方案可以获得一致的图表大小 问题是图表不适合新的打印宽度维度。幸运的是,我们可以在启动打印时执行重画 解决方案是在调用打印时使用canvas.toDataURL()方法将图表呈现为图像,然后在打印后将其
@media print{
自定义我的打印视图。我的图表的问题是,它们的打印大小取决于浏览器窗口的大小。因此,当我的浏览器很大时,画布对于页面来说会太大(我正在使用响应图表)
我试图在@media print{
中重新定义画布的大小,但没有成功
当我打印时(不影响我的浏览器视图),有哪些解决方案可以获得一致的图表大小
问题是图表不适合新的打印宽度维度。幸运的是,我们可以在启动打印时执行重画 解决方案是在调用打印时使用
canvas.toDataURL()
方法将图表呈现为图像,然后在打印后将其切换回画布图表
要检测何时调用函数,webkit提供方法window.matchMedia('print')
(在打印期间为true
,之后为false
),而其他浏览器使用window.onbeforeprint
和window.onafterprint
然后剩下要做的就是使用CSS确保图像响应,即缩放到100%宽度。我为画布使用了自定义打印样式,并使用了自定义右填充:
@media print {
.chartCanvas {
padding-right: 1cm;
}
}
按照链接和Reggie Pinkham的示例,我能够在Angular 2中实现这一点。示例是typescript,但读者应该能够相当轻松地将其应用于常规JavaScript,以便在其他项目中工作。请注意,我只在Linux box上的最新Chrome版本中测试了这一点,因为这对于我的内部公司来说很好y项目
// imports left out here
export class ScaleChartComponent implements OnInit {
private chart:Chart;
private chartNode:HTMLCanvasElement;
private chartImage:HTMLImageElement;
private mediaQueryListener:MediaQueryListListener;
// el is a reference to the root node of my angular html component think of it as just a div container.
constructor(private el:ElementRef) { }
ngOnDestroy() {
this.chart.clear();
this.chart.destroy();
this.chart = null;
this.cleanupPrint();
}
ngAfterViewInit() {
this.drawChart();
this.setupPrint();
}
// need to setup the event listeners here and hold a reference to cleanup afterwards.
public setupPrint() {
if (!window.matchMedia) {
return;
}
var mediaQueryList = window.matchMedia('print');
this.mediaQueryListener = this.handlePrintMediaChange.bind(this);
mediaQueryList.addListener(this.mediaQueryListener);
}
// make sure to cleanup the reference after the fact.
public cleanupPrint() {
if (!window.matchMedia) {
return;
}
var mediaQueryList = window.matchMedia('print');
mediaQueryList.removeListener(this.mediaQueryListener);
this.mediaQueryListener = null;
}
// here's where the magic happens. I first grab the image
// then
public handlePrintMediaChange(mql) {
if (mql.matches) {
let dataUrl = this.chartNode.toDataURL('image/png');
if (this.chartNode && this.chartNode.parentNode) {
this.chartImage = new Image();
this.chartImage.src = dataUrl;
this.chartNode.parentNode.appendChild(this.chartImage);
this.chartService.destroyChart(this.chart);
this.chartNode.parentNode.removeChild(this.chartNode);
}
} else {
// here is where we switch back to non print mode.
if (this.chartImage) {
if (this.chartImage.parentNode) {
this.chartImage.parentNode.removeChild(this.chartImage);
}
this.chartImage = null;
}
// go through and recreate the entire chart again.
this.drawChart();
}
}
public drawChart() {
var chartData = {}; // setup your chart data here.
this.chartNode = this.createChartNode();
if (this.chartNode) {
this.chart = ; // execute your chart.js draw commands here.
}
}
private createChartNode() {
let componentElement = this.el.nativeElement as Element;
let element = componentElement.querySelector(".scale-chart-container");
if (!element) {
console.error("could not find element with class .scale-chart-container");
return null;
}
let chartNode = document.createElement("canvas") as HTMLCanvasElement;
element.appendChild(chartNode);
chartNode = chartNode;
return chartNode;
}
}
请注意,我遗漏了Chart.js命令和数据,因为这些命令和数据会因人员而异。我有一个外部服务来处理我遗漏的内容
我希望这能帮助那些对Reggie的答案感到困惑的人。如果你的图表很简单,试着使用css
@media print {
canvas.chart-canvas {
min-height: 100%;
max-width: 100%;
max-height: 100%;
height: auto!important;
width: auto!important;
}
}
这里有一个简单的修复方法,基于它,比Stephen的答案更容易实现:
//修复chartjs打印:
window.onbeforeprint=(ev)=>{
for(Chart.instances中的变量id){
让instance=Chart.instances[id];
设b64=instance.toBase64Image();
设i=新图像();
//代替下面的内容,您可以在
//决定将其更改为什么的图表。这对我很有用
//然而:
i、 style.maxWidth=“100vw”;
i、 src=b64;
让parent=instance.canvas.parentNode;
instance.tempImage=i;
instance.oldDisplay=instance.canvas.style.display;
instance.canvas.style.display=“无”;
父母、子女(一);
}
};
window.onafterprint=(ev)=>{
for(Chart.instances中的变量id){
让instance=Chart.instances[id];
if(instance.tempImage){
让parent=instance.canvas.parentNode;
parent.removeChild(instance.tempImage);
instance.canvas.style.display=instance.oldDisplay;
删除instance.oldsplay;
删除instance.tempImage;
}
}
};
不确定这是如何解决问题的。由于添加了填充,画布仍然没有调整大小。有人知道这方面的工作示例吗?这个问题提供了一个在Chrome中工作的示例,但显然不是在Firefox/IE中。我确认它在Chrome中工作。此解决方案与我的react UI中的react-chartjs-2包装器组件一起工作。比我迄今为止看到的任何其他解决方案都要简单。我在IE、Chrome、MS Edge中进行了测试。在Firefox中没有得到很好的预览,但我认为Firefox设置存在问题。浏览器没有为我正确打印任何页面。我们只是在画布上添加一个类吗?@Briantum你能分享一下吗你的解决方案?这是一个上帝般的答案。谢谢!不幸的是,这在2.9.4版的Chart.js(在Firefox 84和Chrome 87上测试)上对我不起作用。在chartjs 3 beta9上起作用,谢谢!