I discovered something cool today - Google has a "Static" Maps API. What is that exactly? While Google Maps is very powerful, it requires the use of JavaScript. For simple maps, or for embedding maps into PDFs, you can't use regular Google Maps. This gets around it. The API is a simple URL based service that returns the image in binary form. So for example, to create a map for my area, I'd use this URL:
http://maps.google.com/maps/api/staticmap?center=Lafayette%2C%20LA&zoom=13&key=ABQIAAAAnKqaqda06cMGIKQ6i1ekrRT2yXp%5FZAY8%5FufC3CFXhHIE1NvwkxT2gB6zcbOMt6hlm0jA8TKTSu9K3g&sensor=false&size=400x400
Which produces:
The URL contains multiple arguments. You can see the address, the zoom, a size, and, yes, my Google Maps key. But since I only use it for localhost I'm not too worried about it. The docs contain the full API and demonstrate how you can even use markers and overlays on the maps.
I tried a PDF version and noticed something odd. Whenever I embedded the URL directly in the PDF, it failed. If I fetched the image and save it first, it worked fine, like in the example below:
<cfset key = "ABQIAAAAnKqaqda06cMGIKQ6i1ekrRT2yXp_ZAY8_ufC3CFXhHIE1NvwkxT2gB6zcbOMt6hlm0jA8TKTSu9K3g">
<cfset size = "400x400">
<cfset loc = "Lafayette, LA">
<cfset zoom = 13>
<cfset img = "http://maps.google.com/maps/api/staticmap?center=#urlEncodedFormat(loc)#&zoom=#zoom#&key=#urlEncodedFormat(key)#&sensor=false&size=#size#">
<cfset o = imageNew(img)>
<cfset imageWrite(o, expandPath("./mygooglemap.png"))>
<cfdocument format="pdf" name="mypdf">
<h1>Our Store!</h1>
<img src="/mygooglemap.png" align="right">
<p>
fjdsk lfjklsdjf jfkdk lfklsjkfl dskfd ksl fklfkl fklk lfkldsfklfk lsdfkljsdfkls
fjdsk lfjklsdjf jfkdkl fklsjkfl dskfd kslfklfklfklk lfkldsfklfk lsdfklj sdfkls
fjdsk lfjklsdjf jfkdklfklsjkfl dskfd ksl fklfklfklk lfkldsfklfk lsdfkljsdfkls
fjdsk lfjklsdjf jfkdklf klsjkfl dskfd kslfklfklfklk lfkldsfklfk lsd fkljsdfkls
fjdsk lfjklsdjf jfkdklfklsjkf l dskfd kslfklf klfklk lfkldsfklfk lsdfkljsdfkls
</p>
</cfdocument>
<cfset fileWrite(expandPath("./googlemap.pdf"), mypdf)>
I even whipped up a quick UDF to make it simpler to use:
function getStaticMap(string key, string address, string size, numeric zoom) {
return "http://maps.google.com/maps/api/staticmap?center=#urlEncodedFormat(arguments.address)#&zoom=#arguments.zoom#&key=#urlEncodedFormat(arguments.key)#&sensor=false&size=#arguments.size#";
}
Anyway, there is a lot more to the API, but for those looking for maps you can store offline, or embed in PDFs, then this looks a great resource. (Oh, and let me bitch a bit a little bit here. I really wish the main Google Maps API would let you pass in an address instead of making you have to perform a geolocation request first. It seems silly that I'd need to make 2 HTTP requests for a map when Google should let me just pass the address in the initial map setup request.)
Archived Comments
I just found this last week myself. FWIW I found that it would serve the map even without passing the API key in the URL.
I agree on the 2 HTTP requests which we have to make, seems really redundant and slow things down.
beats the hell out of my apple-shift-4 method
yeah not being able to use the map image directly in creating a PDF is a pain. any idea who to blame?
I too read the same yesterday on Static Maps API from google. Decent idea, just to have the location shown in the map as image rather than loading the complete package of js . this is cool. Will try your UDF as well, thanks.
Paul - if I had to guess why it failed in cfdocument I'd say it was the user agent used to generate the HTML page by the Java package. I can't remember the package offhand (Jason Delmore talked about it recently, it is way old), but if it uses a specific User Agent, Google may blog it. Of course, using imageNew(url) works, so Google isn't blocking the ColdFusion user agent.
Actually - I wonder what the UA is for image requests. I know for CFHTTP it defaults to "ColdFusion something", but it may not for imageNew(). I'll test that today.
ray, a plain cfhttp call works fine just silently fails if within a cfdocument block. i tried (if i remember correctly) various agents, cfsavecontent, etc. only writing out the image worked, which is a pretty messy way to handle this (for a reporting functionality).
Weird. I mean, you can use external URLs in cfdocument, so it should work.
As an FYI, I tested logging the user agent for imageNew(url), and it is Java/1.6.0_17. Obviously that would be different for your own JDK.
Very cool! I didn't know about this at all. Great find.
Static Maps are also targeted at the mobile device market where JS in the browser is not always available. Google did a great presentation at webdu 2009: Fast Maps with the Google Static Maps API
Podcast: http://webdu.com.au/session...
I've been using Google static maps for awhile now to make a printable PDF that serves as a mini brochure. I pull the map image in from google and generate a pdf. Seems to work fine.
Unfortunately this code no longer seems to work. Returns an error:
An exception occurred while trying to read the image.
javax.imageio.IIOException: Can't get input stream from URL!
Well, the post is 7 years old. ;) The Static Map API definitely still works, so the ColdFusion code must be the issue. Probably a change to cfdocument. I don't work with CF much anymore so I can't really help.