Printing ExtJS charts with @media print

2019-07-25 15:22发布

问题:

I have a printing solution for ExtJS objects that seems to work great for everything except for charts.

I've been using @media print CSS tip to create a "printing" div below my viewport (so it is not seen on screen, but it is the only item that is printed when a user clicks the print button).

I do this so that I can control the proportionate sizing of the object so that it fits on the page nicely and so that I can remove "non-printing" elements like toolbars. When I want to print an ExtJS object from my app I add it to this "printing" div and then call document.print.

The CSS for the div looks like this:

@media print {
    @page {size: landscape}
    body * {
      visibility: hidden;
    }
    .printer, .printer * {
      visibility: visible;
    }
    .printer {
      overflow: visible;
      position: absolute;
      left: 0;
      top: 0;
    }
}

This has been working fine for grids and forms and other ExtJS objects.

Now I have to set it up to print some charts but I get a "Layout run failure" error whenever I add the charts to my printer div - the chart does not get created at all. I am pretty sure that this is because the printer div is not actually seen on the screen, and the chart lays itself out based on how it is seen.

Other elements (like grids and forms) do not seem to care if they are visible on the screen to do a layout, so I was wondering is there any way to override this requirement for a chart object? Or is this inextricably buried in the chart code? It would be the ideal handling for me because I would not have to change around my printing mechanism.

Does anyone know if this is possible?

I could create the printable versions of charts inside of a proportionately sized Ext.window.Window object instead that also has my printer class. It would be visible while the layout occurs (about a second) and then get hidden right after I call document.print but obviously that isn't as transparent.

@EvanTrimboli this is the root problem I was trying to handle with that other question.

回答1:

What you've observed - is an optimization in charts, I think it could be disabled, but don't have code snippet right now. You can try to prepare your printer-friendly page while charts are visible, use

var img = chart.save({
     type: 'image/svg+xml'
});

to convert chart into an image, then specify generated image as background or source of the img tag. Not sure if it will work in IE, because of VML format.



回答2:

I ended up putting the chart config in a floating panel. Then I showed the panel and immediately zIndexed it underneath the viewport. Like this (where content is the chart):

// create the printer panel
printable = Ext.create('Ext.panel.Panel', {
    cls: 'printer',
    border: false,
    header: false,
    shadow: false,
    floating: true,
    height: content.length * 670,
    width: 900,
    items: content,
}).show();

// stash the panel where it wont be seen
printable.setPosition(0, 0);
printable.el.dom.style.zIndex = -50;