Export the map to an image, client-side, for printing?

18233
18
06-20-2013 06:48 AM
IanWatkins
New Contributor
I'm guessing the answer is still no and I'm guessing it is still not planned.

I have a requirement to output an image of the final map for the user to save. The map has a tile base with overlays of contour lines generated by our application.

As the application will be run deployed (server and client on a laptop) we don't want to have to build/maintain an ArcGIS 10.1 box just for the purpose of allowing the print service (our tiles are static on our web server). Simple cannot justify it on cost alone.

A simple way to simply output a JPEG/PNG of what the map is showing would be great. A "native" to ESRI JS API "screenshot" is all.

Any plans? Any real reason why not?

It's a little frustrating. "Get away from native desktop apps., go Web 2.0" they said. So we started using Flex/Flash which can do these sort of things clientside. "Get away from Flash/Flex, move to HTML5, it's the future" they said. Now look, we are trying to do desktop type work on a web type app. Can you explain this to your managers, nope. :mad:

Cheers

Ian
0 Kudos
18 Replies
RichardBetts
New Contributor
Hi, Hope I am OK to resurrect this topic. I thought it would be better than starting a new thread on the same topic.
Just wondering if anyone has made progress with this?

I am currently trying to do pretty much the same thing, grab an image of the map (including graphics) to use elsewhere in my application.
I too don't have access to a server side print service/export web map task and have been trying to do this client side. Or as client side as possible.
If I did have access to an ArcGIS server instance it would be at version 10.0 for the time being.

I have made some progress using the html2canvas library to create a html5 canvas element from the map div.
This gives me a 'picture' of the basemap but does not handle any user defined graphics (SVG). I can however separately create an image of the graphics and add this image onto the canvas, being careful to make sure they line up properly.
I then create a smaller copy of the canvas and finally generate a new image from this canvas to add to a new div elsewhere on the page.
The user then has the option to save/print this smaller picture of the map to pdf (using a server side pdf generator).

This all seems to work OK, unless the canvas has been 'tainted' by cross domain content. Which in my case, it will always have been because the basemap service is hosted on a different domain to the application itself.
html2canvas on GitHub offers a php proxy to handle this situation but this appears to store a copy of all the map tiles in the application web server, effectively building up a second cache of map tiles copied from the basemap service.
Not really what I want.

Can anyone suggest a better method or is the canvas element the only option if the print task/service route is not available?

Thanks

Richard
0 Kudos
PamBond
New Contributor III

I am trying to do the same thing - get a "screenshot" of my mapDiv.  I have been messing around with html2canvas as well and I can successfully get a basemap image and graphics image but am not sure how to "layer" the graphics image over the basemap image.  Here is the code I have so far:

$("btnSave").click(function(){

     html2canvas($("#mapDiv"), {

          "useCors": true, //to get basemap

          onrenderer: function(canvas1) {

               theCanvas = canvas1;

               //convert and download as image

               Canvas2Image.saveAsPNG(canvas1);

          }

     });

     html2canvas($("#mapDiv"), {

          "useCors": false, //to get overlying graphics

          onrenderer: function(canvas2) {

               theCanvas = canvas2;

               //convert and download as image

               Canvas2Image.saveAsPNG(canvas2);

          }

     });

})

Not sure how to now put canvas2 on top of canvas1 and create a new image.

Thanks in advance.

0 Kudos
JeffPace
MVP Alum
At the moment, it still has to be serverside.

I ventured down the html5 canvas path as well, but i still support ie7/8, so its out

Flash/Flex out for many many reasons, not limited to security, update-ability, avoiding plugins, "a future", etc..

Does the ESRI api need a map.toImage() method that renders tiles/dynamic/graphics accurately? absolutely.  Are we there yet? Not even close
0 Kudos
JianHuang
Occasional Contributor III
If you can see everything in the map, why it has to go through a proxy to get other things? And img tags from the tiled map service are not contrained by cross-domain policy.



Hi, Hope I am OK to resurrect this topic. I thought it would be better than starting a new thread on the same topic.
Just wondering if anyone has made progress with this?

I am currently trying to do pretty much the same thing, grab an image of the map (including graphics) to use elsewhere in my application.
I too don't have access to a server side print service/export web map task and have been trying to do this client side. Or as client side as possible.
If I did have access to an ArcGIS server instance it would be at version 10.0 for the time being.

I have made some progress using the html2canvas library to create a html5 canvas element from the map div.
This gives me a 'picture' of the basemap but does not handle any user defined graphics (SVG). I can however separately create an image of the graphics and add this image onto the canvas, being careful to make sure they line up properly.
I then create a smaller copy of the canvas and finally generate a new image from this canvas to add to a new div elsewhere on the page.
The user then has the option to save/print this smaller picture of the map to pdf (using a server side pdf generator).

This all seems to work OK, unless the canvas has been 'tainted' by cross domain content. Which in my case, it will always have been because the basemap service is hosted on a different domain to the application itself.
html2canvas on GitHub offers a php proxy to handle this situation but this appears to store a copy of all the map tiles in the application web server, effectively building up a second cache of map tiles copied from the basemap service.
Not really what I want.

Can anyone suggest a better method or is the canvas element the only option if the print task/service route is not available?

Thanks

Richard
0 Kudos
RichardBetts
New Contributor
Thanks for the replies.
Jian - I am more of a GIS person than a web person, but here's how I understand it...

If I don't use a proxy to read the basemap tiles onto the new canvas, the canvas is considered to be tainted and I will be unable to use the toDataURL() method to create an image data URL which I then intend to use as the source of an img element.
I need the img element because a canvas will never appear on my pdf, tainted or not.
In other words - 'If the canvas has been tainted, you can no longer pull data back out of the canvas'.

Using html2canvas with the proxy very nearly gives me what I need, other than this issue of the map tiles being physically copied to my web server. I guess I assumed the proxy would work in the same way as it does for wms capabilities requests, as a 'middleman' to make the responses appear to be from the same domain. 

Jeff -Totally agree. Thanks
0 Kudos
PhilReese1
New Contributor
Rich,

I'm doing something similar and I talked to a couple folks around the office and they suggested using a Scheduled Task a few times a day on the server to delete the local cache of images that are generated.
0 Kudos
MayJeff
Occasional Contributor

Can you show me a sample you use for printing ?  Thanks.

0 Kudos
by Anonymous User
Not applicable

old thread resurrection time!

I'm working on making a Screenshot widget in WebApp Builder using html2canvas.  I will post this thread in WAB Widgets forum soon but thought to post here first as you all have experience with html2canvas.

I have a working demo of a page that creates a screenshot and opens the standard Save As... browser dialogue here - kevinsagis/ScreenshotDemo · GitHub  this is everything all in one HTML file. Just open it localhost or a IDE like Visual Studio. (note this is a repost of a js Fiddle because it does not work on js Fiddle for some reason, all credit for all authors in comments and Read Me)

I also have the work in progress widget where I am porting this code into WAB, here.  kevinsagis/Screenshot-Widget · GitHub .   This not only runs the DOM through html2canvas, it then converts it into a "blob" (not sure really what this is... ?? .. but hey it works) then makes the browser open a "Save As.." dialogue for the DOM element as a .PNG image file.  So I intend to grab the whole viewport, via the DOM "main-page" or "map" node in WAB. Would like main-page so as to grab widgets, attrib table. Users want a "print screen" button. This is the closest we can get of course with Javascript, considering browser security limitations.

So when I ported the code into WAB,  pointed it to main-page and said

     var windowScreenShot = dom.byId("main-page");

     html2canvas((windowScreenShot), {

         onrendered: function (canvas) {

             theCanvas = canvas;

             window.open("", canvas);      }     });

It only generates a blank page in a new window.  So I tried smaller DOM nodes like buttons, still no go. In the console it just shows <canvas width="142" height="45"></canvas> when I log 'canvas'.  And opens a blank window.  I removed the toBlob and SaveAs because even the html2canvas isn't working yet.

Ideas anyone? Scoping? Something else?  I have seen in misc. threads that complex DOM sometimes creates issues for html2canvas although I would think WAB would be fine. And cross domain can be an issue. Maybe I need a proxy or something? But since it is local on node.js I thought that would not be it.

0 Kudos
JeffPace
MVP Alum

We do all of our page building client side (including pdf generation) but still use server side operations to generate the map.  A couple reasons.

We still support older IE, which uses vml, so we cant go pure canvas.

We support non ESRI basemaps

www.mymanatee.org/gisapps/mobile/index.html

Printing is on the tools tab.

0 Kudos