printing maps?

6,928 views
Skip to first unread message

Robert (mapsmarker.com)

unread,
Aug 12, 2012, 4:12:38 PM8/12/12
to leafl...@googlegroups.com
A user of my plugin mapsmarker.com asked if there is a better way to print a leaflet map than making and printing a screenshot.
Does anyone know of a plugin which adds a print button for example? Or which other ways could one use to add a usable printing functionality to leaflet?

Jayesh Mori

unread,
Sep 11, 2012, 11:47:06 AM9/11/12
to leafl...@googlegroups.com
I am looking for the similar functionality. Did you find the solution yet?

Robert Harm

unread,
Sep 11, 2012, 11:55:53 AM9/11/12
to leafl...@googlegroups.com
not yet
--
 
 
 

Eleanor Tutt

unread,
Oct 22, 2012, 6:46:41 PM10/22/12
to leafl...@googlegroups.com
I am also looking for a good way to "print" a leaflet map - either by making a PDF or png.  I have found two almost-solutions, neither one of which gets me 100% where I need to be - but depending on your requirements, they might work for you.  I'll share what I'm working on - and I would be grateful for any advice on what else to try because I am still a novice.

1) Tegan Snyder has created Leaflet-Save-Map-to-PNG here: https://github.com/tegansnyder/Leaflet-Save-Map-to-PNG 

I am on a shared server and had to alter some of the settings in my php.ini to get it to work for me - I think because the variables being passed are so long?  But once I did that, it worked like a charm - really nice!  It relies, though, on html2canvas and I am having trouble with both Internet Explorer as well as with including my geojson layer.  If I render the geojson layer using  the Leaflet setting "L_PREFER_CANVAS = true;" then it gets saved to the PNG, but that screws up some other click events I am using.


I have been able to install PhantomJS and it does a great job taking screenshots of my leaflet map.  However, the way it works is that you tell it the url of the webpage you want to get a screenshot of and then it "loads" the webpage itself.  So it doesn't know what the map actually looks like client-side after the user has clicked and panned and zoomed.  Leaflet-hash creates "permalinks" to the correct map center and map zoom level giving urls that have some of the client-side changes "built in", and PhantomJS understands those permalink urls and takes the correct screenshot.  However, I don't know how to take into account other click events - for example, my geojson layer allows people to select and highlight individual features as well as change the underlying variable used to symbolize the features.  I don't know how to  pass those to PhantomJS.

Please, please, please - if anyone has suggestions for either solution, I need all the help I can get!

Thanks so much,
Eleanor

Adam Eskreis

unread,
Oct 25, 2012, 6:12:16 PM10/25/12
to leafl...@googlegroups.com
As far as I know, leaflet maps print just fine.  You will need to design a print page using a print style sheet, but as long as you are using img tags for the tiles (which I believe is the default) then the map should print just fine.  You would need to add any custom UI element to the map if you wanted a "print" button, but this can all be accomplished with some simple javascript and css.


On Sunday, August 12, 2012 4:12:38 PM UTC-4, Robert (mapsmarker.com) wrote:

Eleanor Tutt

unread,
Oct 25, 2012, 6:28:44 PM10/25/12
to leafl...@googlegroups.com
Adam - I wish that were true!  Maybe the underlying gist of what you are saying is that I should rethink the design of my map - and that thought has occurred to me - in order to save myself printing headaches.  I have a base map and an overlay with transparent styling, and it looks pretty awful printed (at least in comparison to how it appears on the screen).  The opacity is all screwed up and you can only see the top-most layer.

I am currently experimenting with MapFish Snapshot, per the helpful advice of someone off-forum who had success with it.  That being said, it is slow-going to understand/configure and feels so unfortunately "heavy" compared to the simple elegance of Leaflet itself.

Anyway, I am still working on the problem and would love to see examples if anyone is using MapFish Snapshot with Leaflet.  Especially if you are using a geojson layer.

Thanks,
Eleanor

--
 
 
 

Adam Eskreis

unread,
Oct 25, 2012, 6:35:34 PM10/25/12
to leafl...@googlegroups.com
Are you saying that you have a vector layer which has varying alpha values?  If so, I believe Leaflet uses canvas rendering, in which case you can save the contents of the canvas to a bitmap and then load that bitmap into an IMG tag, which you can then overlay on top of the map using javascript/css. 

Here you can see how you can capture the contents of a canvas element:

http://stackoverflow.com/questions/923885/capture-html-canvas-as-gif-jpg-png-pdf

As for the basemap tiles, those should print fine without issue.  Makes sense in theory, not sure if it will work in practice though.

Eleanor Tutt

unread,
Oct 25, 2012, 6:58:15 PM10/25/12
to leafl...@googlegroups.com
Thanks for that link, Adam!  I did mess around a bit with the canvas approach via html2canvas - but that requires me setting my geojson vector layer as canvas, which in turn appears to break the ability to select and unselect the individual features.  My map is something like the Choropleth example here: http://leaflet.cloudmade.com/examples/choropleth.html but, yes, with varying alpha values and additional onclick events.

I didn't entirely exhaust the canvas approach, though, and it may be is probably worth another look - maybe there is a way to render the geojson vector layer as canvas and handle click events differently.

I really appreciate your help - it's nice to have a fresh set of eyes on the problem.

Eleanor

Adam Eskreis

unread,
Oct 25, 2012, 7:12:43 PM10/25/12
to leafl...@googlegroups.com
Hmm yea if you are using SVGs, you will not get great printing results.  I took a quick look at the leaflet source, and while you are correct that the L.Path.Canvas class does not properly implement click events, the L.Polygon.Canvas class has a method called "_containsPoint".  Perhaps rather than using Path elements, you could use Polygon elements, and then attach a click handler to the canvas, which will check to see if where the user clicked is contained within the polygon.  This would probably take some time to implement to determine whether it would work or not, but it seems plausable.

I will say though it annoys me a bit that the click handler does not work for canvas paths.  I may take it upon myself to implement this tonight when I get home from work.

Arnie Shore

unread,
Oct 25, 2012, 7:14:48 PM10/25/12
to leafl...@googlegroups.com
With the layer of interest on-screen, won't a simple 'print-screen'
operation and pasting that into any convenient graphic/image package
work for you?

it seems to me that end-runs any of the software artifacts that
generate the on-screen image. It's worked for me in a number of
PPT-based presentations.

AS

thecolour blue

unread,
Oct 26, 2012, 4:56:03 AM10/26/12
to leafl...@googlegroups.com
Hi,

I have also run into this problem trying to generate vector pdfs from leaflet svg.

Can someone explain what exactly is the problem? Given a simple svg, most browsers can generate vector pdfs from them by printing (I've tried ff/chrome with http://upload.wikimedia.org/wikipedia/commons/9/9a/Degree-Radian_Conversion.svg)- but my leaflet maps do not print properly in any of ff/chrome/safari and they all seem to garble them a little differently. Is it something to do with the css styling that leaflet creates? or the transparency perhaps? So it is really a browser bug? If that is the problem perhaps it would be simple enough to create a little function for leaflet that generates "nice" svg which can be easily converted to a vector pdf- I'm sure a lot of folks (me included) would really like this. The d3 folks seems to have encountered something like this problem and came up with this:

http://incontemplation.com/blog/?p=574

Any ideas if something along these lines would work for leaflet too?

-a

Eleanor Tutt

unread,
Oct 26, 2012, 9:35:56 AM10/26/12
to leafl...@googlegroups.com
Adam - that does sound plausible in theory, though I'm quickly getting in over my head.  My geojson file has type = polygon already - so It seems L.GeoJSON automatically renders GeoJSON polygon elements as paths?  Do you mean that I need to loop through my data using L.Polygon with lat/longs and forgo the L.GeoJSON and onEachFeature shortcuts?  I apologize if that is a stupid question.  Also, if you were interested in tackling the canvas path click handler as you mentioned, that would be *amazing* !!!

Arnie - Are you referring to the "Print Screen" key on the keyboard?  If so, that does indeed work to get a clean image - but it isn't very good from a user experience perspective.

thecolour blue - I assume a big part of the problem with Leaflet is the transparency issue when you have multiple layers on top of one another (just based on what I've noticed in trying to print).  That d3 link is really interesting...I second your question about whether something similar would work for leaflet.

Eleanor

Adam Eskreis

unread,
Oct 26, 2012, 10:31:36 AM10/26/12
to leafl...@googlegroups.com
I took another look at the leaflet source and it seems that leaflet is already creating L.Polygon elements if the GeoJSON type is polygon, so that's one less thing you need to do.  However, you would still need to implement the event handlers manually and the collision detection manually.  I couldn't see it being all that difficult though.  I would attach an event handler to the map, then in the click handler, you would loop through your GeoJSON FeatureGroup and test if the lat/lon of where you clicked (this should be part of the event object) is within any of the polygons.  If a polygon is found, then you would apply the appropriate style changes to indicate to the user that a change has occurred.  It's a bit round-a-bout but it should get the job done.  Best of luck.

thecolor blue - the problem with this method is it requires the user to open the javascript console, something not every browser has built in, and something a regular user should never need to touch.

thecolour blue

unread,
Oct 26, 2012, 10:54:08 AM10/26/12
to leafl...@googlegroups.com


On Friday, October 26, 2012 3:31:36 PM UTC+1, Adam Eskreis wrote:
I took another look at the leaflet source and it seems that leaflet is already creating L.Polygon elements if the GeoJSON type is polygon, so that's one less thing you need to do.  However, you would still need to implement the event handlers manually and the collision detection manually.  I couldn't see it being all that difficult though.  I would attach an event handler to the map, then in the click handler, you would loop through your GeoJSON FeatureGroup and test if the lat/lon of where you clicked (this should be part of the event object) is within any of the polygons.  If a polygon is found, then you would apply the appropriate style changes to indicate to the user that a change has occurred.  It's a bit round-a-bout but it should get the job done.  Best of luck.

thecolor blue - the problem with this method is it requires the user to open the javascript console, something not every browser has built in, and something a regular user should never need to touch.


For sure- I wouldn't recommend that as a solution. However, if we could find a way to produce some kind of conforming svg which can either be saved to a file or printed directly from the browser- then it shouldn't be too hard to wrap this function in a bit of javascript which gets called on a button press or perhaps when the user tries to print.

I just had a look again at the Webkit nightly, and it does a nice job making vector pdf's of some of the examples on the leaflet page (which ff/chrome do not print properly), but it still does not handle my own example. So, the support for svg is improving somewhat, but its still not clear to me which elements are causing the problem with the printing- if we had a clearer idea where the issue were then perhaps it could be an option to turn them off just for the print job (I would be happy with this...).

Eleanor Tutt

unread,
Oct 26, 2012, 11:27:34 AM10/26/12
to leafl...@googlegroups.com
Thanks, Adam - this is helpful. 

--
 
 
 

Adam Eskreis

unread,
Oct 26, 2012, 12:22:50 PM10/26/12
to leafl...@googlegroups.com
You're very welcome, and if you do find a solution, I'd love to hear how you finally solved it.

Best of luck.

Eleanor Tutt

unread,
Oct 26, 2012, 2:33:17 PM10/26/12
to leafl...@googlegroups.com
I will definitely report back.

I realized the canvas-based solution is still going to be problematic in IE8 (ugh - I'd forced myself to forget about IE8 for a while)...and I have reached the point where I have to decide whether a print button is going to make it into the first iteration of our website (as I'd hoped) or whether it will have to be put on hold for a couple weeks.

Unfortunately, looks like I am going to have to put it on hold and revisit the issue a bit later, as I am already behind-schedule.

I do appreciate everyone's help and I promise I will return in November with an update!  I'm not giving up - just need to take a short break.

Thanks,
Eleanor

--
 
 
 

Lucas Toneatto

unread,
Oct 24, 2014, 9:16:04 AM10/24/14
to leafl...@googlegroups.com
Hola, necesitaría un ejemplo de como utilizar lo que usted dice. Muchas gracias

Rajat Chopra

unread,
Feb 4, 2015, 6:34:50 AM2/4/15
to leafl...@googlegroups.com
Hello Robert,

Did you got a solution to your problem, as i am new user of lealflet and was trying to print a map in leaflet  but was not successful,

Could you please help.

Diff

unread,
May 23, 2016, 3:42:53 PM5/23/16
to Leaflet
I know this post is nearly 4 years old, but I'm curious if you came up with a solution and what you figured out.
Reply all
Reply to author
Forward
0 new messages