调整chart.js画布的大小以进行打印

时间:2017-01-16 11:07:10

标签: canvas chart.js

我使用@media print {来自定义我的打印视图。我的图表的问题是它们的打印大小取决于浏览器窗口的大小。因此,当我的浏览器很大时,画布对于页面来说太大了(我使用了响应式图表)

我试图在@media print {内重新定义画布的大小,但没有成功。

打印时获得一致图表大小的解决方案有哪些(不影响我的浏览器视图)?

enter image description here

5 个答案:

答案 0 :(得分:10)

如果您的图表很简单,请尝试仅使用css

@media print {
    canvas.chart-canvas {
        min-height: 100%;
        max-width: 100%;
        max-height: 100%;
        height: auto!important;
        width: auto!important;
    }
}

答案 1 :(得分:6)

问题是图表不适合新的打印宽度尺寸。幸运的是,我们可以在启动打印时执行重绘。

解决方案是在调用打印时使用canvas.toDataURL()方法将图表渲染为图像,然后在打印后将其切换回画布图表。 More on toDataURL()

要检测何时调用您的函数webkit提供方法window.matchMedia('print')(在打印期间true或之后再次false),而其他浏览器使用window.onbeforeprint和{ {1}}。 More on print methods

所有剩下要做的就是确保图像使用CSS响应,即缩放到100%宽度。

答案 2 :(得分:0)

我使用自定义打印样式为画布添加了自定义右侧填充:

from tkinter import *



class MainWindow():

 def __init__(self):
    def printing():
        print("This is going to print:", i)
    def ButtMaker1(frame1,title,CMDVar,xLoc,yLoc):
        print(title,xLoc,yLoc)
        Title = title
        cmdVar = CMDVar()
        FrameAnchor = frame1
        NewButton = Button(FrameAnchor, text = Title, command = cmdVar)
        NewButton.grid(row = xLoc, column = yLoc)
    window = Tk()
    frame1 = Frame(window)
    frame1.grid(row =1, column = 1)
    for i in range(10):
            print(i)
            title = ("Bob is :" + str(i))
            xLoc = i
            yLoc = i + 1
            CMDVar = printing
            ButtMaker1(frame1,title,CMDVar,xLoc,yLoc)





    window.mainloop()

<MainWindow()

答案 3 :(得分:0)

按照链接和Reggie Pinkham的例子,我能够在Angular 2中完成这项工作。这个例子是打字稿,但是读者应该能够很容易地将它改编成普通的javascript来工作其他的项目。注意我只在linux盒子上的最新版Chrome中测试了这个,因为这对我的内部公司项目来说很好。

// 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命令和数据,因为这将根据此人的不同而有所不同。我有一个外部服务处理我遗漏的内容。

我希望这可以帮助那些对如何摆脱雷吉的答案感到头疼的人。

答案 4 :(得分:0)

这是一个基于Reggie's answer的简单解决方案,它比Stephen的回答要容易实现:

import numpy as np

matrix = np.array([[0.25656927,0.31030828,0.23430803,0.25999823,0.20450112,0.19383106,
  0.35779405, 0.36355627, 0.16837767, 0.1933686, 0.20630316, 0.17804974,
  0.06902786, 0.26209944, 0.21310201, 0.12016498, 0.14213449, 0.16639964,
  0.33461425, 0.15897344, 0.20293266, 0.14630634, 0.2509769,  0.17211646,
  0.3922994,  0.14036047, 0.12571093, 0.25565785, 0.18216616, 0.0728473,
  0.25328827, 0.1476636,  0.1873344,  0.12253726, 0.16082433, 0.20678088,
  0.33296013, 0.03104548, 0.14949016, 0.05495472, 0.1494042,  0.32033417,
  0.05361898, 0.14325878, 0.16196126, 0.15796155, 0.10990247, 0.14499696]])

n = len(matrix[matrix > 0.18])
print(n)