Resize on print

3,522 views
Skip to first unread message

Ricardo

unread,
May 29, 2011, 2:42:07 PM5/29/11
to d3-js
I've been trying to get this to work for the past 3 days,
unsuccessfully. I have create a simple chart that resizes when the
window containing it resizes. The problem comes when I try to print
the same chart. The chart is printed smaller or cropped depending on
the size of the window at the moment of the print command. In google
chrome the resize event is being called but not with the size of the
printed page but with the size of the window browser. Maybe this is
trying to push it in terms of printing from the browser, but I really
need the liquid flow charts that print nicely. Any ideas?

I'm using jQuery to attach a handler for the window.resize event that
later gets sent to all elements with the class "resizable" as such:

$(document).ready(function() {
$(window).resize(function() { $('.resizable').resize(); })
});

The chart is very simple and I have encapsulated it into an anonymous
function so that I don't pollute the global namespace:

<div id="chart" class="resizable"></div>
<script type="text/javascript">

(function(ce) {

var data = [ 10, 20, 30, 40 ];

function draw() {

var w = $(ce).width(),
h = $(ce).height();

// console.log('size', w, h);

d3.select(ce).selectAll('svg').remove();

var chart = d3.select(ce)
.append('svg:svg')
.attr('width', w)
.attr('height', h)
.append('svg:g');

var x =
d3.scale.ordinal().domain(d3.range(data.length)).rangeBands([0, w],
0.2),
y = d3.scale.linear().domain([0, d3.max(data)]).range([0, h]);

chart.selectAll('rect')
.data(data)
.enter().append('svg:rect')
.attr('x', function(d, i) { return x(i); })
.attr('y', function(d) { return h - y(d); })
.attr('width', x.rangeBand())
.attr('height', function(d) { return y(d); });

}

$(ce).resize(function() {
draw();
});

draw();

})('#chart');

</script>

Mike Bostock

unread,
May 29, 2011, 2:51:12 PM5/29/11
to d3...@googlegroups.com
Hmm. I might try using a CSS @media print rule to force a reasonable
size for the SVG when you print it. Something like:

@media print {
svg {
/* reasonable size for svg goes here */
}
}

Actually, maybe setting the body size in @media print might be more
predictable. Try it and see?

Mike

Ricardo

unread,
May 29, 2011, 10:10:38 PM5/29/11
to d3-js
I've been trying all combinations possible and nothing seems to work.
Chrome does trigger the resize event before printing but it does so
with the size of the browser window as opposed to the page. Will
continue to try and figure this out. Thanks for the help.

- R

Mathew Johnston

unread,
Dec 20, 2013, 2:13:18 PM12/20/13
to d3...@googlegroups.com, rmar...@stanfordalumni.org
Hi Ricardo,

Where you able to resolve this? I'm having the same problem printing D3/NVD3 charts in both chrome v31 and IE 11 - haven't tried Firefox yet. CSS @media print rules can control the size of the area the chart appears in, but simply causes cropping rather than scaling. 

Thanks!
Mat

Ricardo Marimón

unread,
Dec 20, 2013, 4:47:59 PM12/20/13
to Mathew Johnston, d3...@googlegroups.com, rmar...@stanfordalumni.org
Sorry. I could never get it working. 

Ricardo Marimón
Director Organización Palo Alto

Amelia Bellamy-Royds

unread,
Dec 21, 2013, 10:45:36 PM12/21/13
to d3...@googlegroups.com, Mathew Johnston, rmar...@stanfordalumni.org
Try this:
  • Set a container div that will use the appropriate amount of space (the default 100% width will probably be fine in many cases, but you'll need a defined height and you might still want to use CSS media queries to finesse the width or height on the printed page).
  • Within your draw/update/resize method, query the height and width of the container div.
  • (So far, we're the same as Ricardo's example, here's what's different:)
    Create your SVG inside the container, and either set it's height and width attributes to 100% or use CSS to do the same.
  • Add a "viewBox" attribute to the SVG and set it to "0,0, w, h" where w and h are the current width and height of the container in pixels.
  • (Optional, but recommended if you have any text, circles, or anything else that would look wonky if squashed or stretched:)
    Add a "preserveAspectRatio" attribute set to "xMidYMid meet" or any of the other "meet" variations (see link below) .
Now, your SVG will automatically scale to the width and height available.  However, this does mean that everything will scale, including text; so text labels may end up very large or very small if there is a significant change in size from the screen to the page.  This is the main reason why this method isn't widely recommended for adapting to a change in window size.  

(Although, if you don't have any text, you can skip redrawing on all the resize events and just set the viewBox attribute with any width or height values you like, your chart will be drawn as if it was that many pixels wide and high and then scaled to fill the space.)

Example based on Ricardo's code (I had to replace the JQuery functions, since I couldn't figure out how to get JSFiddle to load two libraries at once):

The specs for viewBox and preserveAspectRatio:
http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute

Hope that helps,
--ABR



On Friday, December 20, 2013 2:47:59 PM UTC-7, Ricardo wrote:
Sorry. I could never get it working. 
Reply all
Reply to author
Forward
0 new messages