4

I am looking for a method to efficiently print Google maps that have been implemented on a site using the google maps api v3.

I have seen some people using just the window.print js and then

@media print
{
    body * { visibility: hidden; }
    #map * { visibility: visible; }
    #map {visibility: visible;position:absolute; top: 5px; left: 5px;}
}

Currently a larger map is displayed to users using fancybox and I have added a print button to this. Ideally I just want to add some jquery or similar to print the map.

However this doesn't seem to really work. Has anyone got any suggestions on the best way to do this

Kara
  • 6,115
  • 16
  • 50
  • 57
Purple Hexagon
  • 3,538
  • 2
  • 24
  • 45

6 Answers6

19

I guess by simple yet subtle DOM manipulation, you can get the "snapshot" of your Google Maps (well, theoretically - any maps :)) viewer and perfectly print it in any browsers. Assuming $mapContainer is the main container of your maps, related code is:

// printAnyMaps ::
function printAnyMaps() {
  const $body = $('body');
  const $mapContainer = $('.map-container');
  const $mapContainerParent = $mapContainer.parent();
  const $printContainer = $('<div style="position:relative;">');

  $printContainer
    .height($mapContainer.height())
    .append($mapContainer)
    .prependTo($body);

  const $content = $body
    .children()
    .not($printContainer)
    .not('script')
    .detach();

  /**
   * Needed for those who use Bootstrap 3.x, because some of
   * its `@media print` styles ain't play nicely when printing.
   */
  const $patchedStyle = $('<style media="print">')
    .text(`
      img { max-width: none !important; }
      a[href]:after { content: ""; }
    `)
    .appendTo('head');

  window.print();

  $body.prepend($content);
  $mapContainerParent.prepend($mapContainer);

  $printContainer.remove();
  $patchedStyle.remove();
}

Note that you can flexibly replace $printContainer by any print template. Here I just use a simple <div> that serves as a placeholder of the snapshot.

Working code here: http://jsfiddle.net/glenn/6mx21ted

Glenn Mohammad
  • 3,871
  • 4
  • 36
  • 45
  • This function is printing properly, But there is a slight problem with it. It is printing 3 pages even though map can be fit in only one page. – Pulkit Pithva Apr 08 '16 at 12:34
  • I tried this, but it shows blank map, only Markers is displayed – Ronak Patel Apr 26 '16 at 07:37
  • @RonakP Mind to share your code in a place like JSFiddle or GitHub so that I can better understand the cause and improve the solution? – Glenn Mohammad Apr 26 '16 at 11:24
  • Yes, It was the same as yours, not a bit different. What can be affacting? – Ronak Patel Apr 26 '16 at 12:45
  • @RonakP I've improved my solution (as well as in the JSFiddle). I think the issue lies within some of Bootstrap's `@media print` styles, if you happen to use it in your code. @Pulkit Pithva It could possibly be related to Bootstrap, too - no time to check that one, though. – Glenn Mohammad Apr 29 '16 at 20:22
  • Thank you @GlennMohammad for this. So kind. – Ronak Patel Apr 30 '16 at 10:35
  • Thank you very much. Tried too many things to fix it. Finally got the simplest solution. – Braj Mar 28 '17 at 19:26
  • 1
    Thanks for this workaround, in my site works with just the css part of your : ' @media print { img { max-width: none !important; } a[href]:after { content: ""; } } ' – Igor Trindade Apr 23 '17 at 16:15
  • Works great. Make sure the map is in a div otherwise when you close the Print dialog, it will appear at the top of the page. – Atchoum Nov 15 '17 at 16:29
5

Please note, if you're also using Bootstrap it will break map printing for you. Add this code:

@media print {
  img {
    max-width: auto !important;
  }
}

See Twitter Bootstrap CSS affecting Google Maps.

tempranova
  • 929
  • 9
  • 13
2

In HTML, #Gmap is the div you display the google map, and Print Button will call function gmapPrint() once it has been clicked.

<!-- HTML -->
<div id="Gmap"></div> 
<div onclick="gmapPrint();">Print Button</div>

In JavaScript, the gmapPrint() function read the map details and write it on a new window. Then print the new window.

<!-- JS Script -->
function gmapPrint() {
    var content = window.document.getElementById("Gmap"); // get you map details
    var newWindow = window.open(); // open a new window
    newWindow.document.write(content.innerHTML); // write the map into the new window
    newWindow.print(); // print the new window
}
Jingwen
  • 81
  • 5
  • hi @Jingwen i want to print the map with the page content too? I have receipt layout to print with the map location in it when i use window.Print() it prints all the text in a div but unable to print the google Map? any idea? suggessions? – SHEKHAR SHETE May 05 '14 at 09:07
1

Try this if you want to print the full size of the map for every browser:

function printMap() {
$('<style media="print">')
    .text(`
   body {
    width: ${screen.width}px;
    height: ${screen.height}px;
  }
  body { zoom: 50% !important;}
`)
    .appendTo('head');

window.print();
return false;

}

Kriss
  • 41
  • 5
  • they got answer in comment and its too late for answer to this question – hio Sep 23 '20 at 10:49
  • But a helpful answer. Previous answers are not worked for me (sometimes previous answers are not printing properly). – RSB Oct 16 '21 at 08:06
0

You can use html2canvas.js to convert map div to canvas element, then you can print it as image. Below code works perfect for me:

HTML

<div id="map" style="width:500px;height:500px;"></div>
<input type="button" value="Print Map" class="printBtn" />

JavaScript

var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 13,
            center: defLocation,
            mapTypeId: 'satellite',
            streetViewControl: false
        });      
$(document).on('click', '.printBtn', function () {
            map.setOptions({
                mapTypeControl: false,
                zoomControl: false,
                streetViewControl: false,
                panControl: false
            });
            var printWin = window.open('', '', 'width=1000,height=700');
            var windowContent = '<!DOCTYPE html>';

            html2canvas($("#map"), {
                useCORS: true,
                onrendered: function (canvas) {
                    windowContent += '<html>'
                    windowContent += '<head><title>Print canvas</title></head>';
                    windowContent += '<body>'
                    windowContent += '<img src="' + canvas.toDataURL() + '">';
                    windowContent += '</body>';
                    windowContent += '</html>';
                    printWin.document.open();
                    printWin.document.write(windowContent);
                    printWin.document.close();
                    printWin.focus();
                    setTimeout(function () { printWin.print(); printWin.close(); }, 500);

                    map.setOptions({
                        mapTypeControl: true,
                        zoomControl: true,
                        streetViewControl: true,
                        panControl: true
                    });
                }
            });
        });
Ceyhun
  • 1,354
  • 2
  • 10
  • 10
0

I do not have enough reputation to post comments, but hear me out.

For those of you who are having some issues with the accepted answer, where the map has random tiles out of order and/or some entirely grayed out (the fiddle is doing this for me in the latest version of Chrome), you need to add this little snippet to the CSS that is being injected into the page:

#map_canvas div > img {
        position: absolute;
}

where #map_canvas is the selector of your map. I stumbled upon this answer on an old bug report thread and it is saving my life right now: https://issuetracker.google.com/issues/35825130?pli=1

So here is a "corrected" version of the fiddle: http://jsfiddle.net/nbLr3jtf/

Props still go to @Glenn Mohammad for his original answer!

krokador
  • 39
  • 6