title: Printing Maps from Google Maps API JS V3
body: <p>I have a single-page web app using Google Maps API JS v3 that our shop manager uses (via Chrome) to print customized directions for our drivers. (The reasons for customization aren't relevant to the issue.) He was able to get the directions, put what he wanted to print into the map view, and it would come out looking pretty and give us happy drivers.  Up until roughly three weeks ago, everything worked fine.  But then.... (cue ominous music)</p>
  
  <p>The shop manager came to me and said that the maps weren't coming out right.  Sure enough, while the map <a href="https://i.stack.imgur.com/F87Uo.png" rel="nofollow noreferrer">looked fine on the screen</a>, the <a href="https://i.stack.imgur.com/WqLZf.png" rel="nofollow noreferrer">printed map didn't</a>.
   Apparently, a horizontal area of the map is missing, but the route is still plotted where the roads of the map should be.  (If you notice near Granite City, our poor driver's route takes him through a lake...)</p>
  
  <p>I've supplied the code below.  Since this started without me changing the code, I'm forced to assume this is due to some sort of Chrome or Maps update.  Does anyone have any suggestions to resolve this?</p>
  
  <p>Thanks!</p>
  
  <pre><code>&lt;html&gt;
  &lt;!DOCTYPE html&gt;
  &lt;head&gt;
  
      &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"&gt;
      &lt;/script&gt;
      &lt;script src="./printThis.js"&gt;
      &lt;/script&gt;
      &lt;style&gt;
        @media screen {
          html,
          body {
            font-family: Arial, sans-serif;
            height: 100%;
            margin: 0;
            padding: 0;
          }
  
          .container {
            height: 100%;
            position: relative;
          }
  
          input {
            font-size: 14px;
          }
  
          h1 {
            color: #525454;
            font-size: 22px;
            margin: 0 0 10px 0;
            text-align: center;
          }
  
          #hide-listings,
          #show-listings {
            width: 48%;
          }
  
          hr {
            background: #D0D7D9;
            height: 1px;
            margin: 20px 0 20px 0;
            border: none;
          }
  
          .map-landscape {
            bottom:0px;
            height: 8in;
            width: 10in;
            left: 322px;
            top:0px;
            position: absolute;
          }
  
          .map-portrait {
            bottom:0px;
            height: 10in;
            width: 8in;
            left: 322px;
            top:0px;
            position: absolute;
          }
  
          .options-box {
            background: #fff;
            border: 1px solid #999;
            border-radius: 3px;
            height: 100%;
            padding: 10px 10px 30px 10px;
            text-align: left;
            width: 300px;
          }
  
          #pano {
            width: 400px;
            height: 300px;
          }
  
          #search-within-time-text {
            width: 84%;
          }
  
          .text {
            font-size: 12px;
          }
  
          #toggle-drawing {
            width: 27%;
            position: relative;
            margin-left: 10px;
          }
  
          #zoom-to-area-text {
            width: 70%;
          }
  
          #zoom-to-area {
            width: 24%;
          }
  
          #directions {
            font-size: smaller;
            margin-bottom: 1em;
            line-height: 120%;
          }
  
          .gm-style-iw {
            line-height: 14px;
          }
  
  
        #divButtons p {
          margin:.5em;
          text-align: left;
        }
        }
        @media print {
          .options-box {
            visibility:hidden;
            height:0px
          }
  
          #directions {
            width:100%;
          }
  
          #printContainer.map #directions {
            visibility: hidden;
          }
  
          #printContainer.map #directions {
            visibility: hidden;
          }
  
          #printContainer.directions #map {
            visibility: hidden;
          }
  
          #printContainer.both #directions {
            page-break-after: never;
          }
        }
      &lt;/style&gt;
      &lt;title&gt;&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
      &lt;div class="container"&gt;
          &lt;div class="options-box"&gt;
              &lt;div id="options"&gt;
                  &lt;h1&gt;Driver Directions&lt;/h1&gt;
                  &lt;p&gt;&lt;label for="origin"&gt;From:&lt;/label&gt;&lt;br&gt;
                  &lt;input id="origin" placeholder="Directions From:" type="text" value=""&gt;&lt;input id="fromMadison" type=
                  "button" value="Madison Yard"&gt;&lt;/p&gt;
                  &lt;p&gt;&lt;label for="destination"&gt;To:&lt;/label&gt;&lt;br&gt;
                  &lt;input id="destination" placeholder="Directions To:" type="text" value=""&gt;&lt;input id="toMadison" type=
                  "button" value="Madison Yard"&gt;&lt;/p&gt;
              &lt;/div&gt;
              &lt;div id="divButtons"&gt;
                  &lt;p style="text-align:center;"&gt;&lt;input style="height:50px;width:150px" id="getDirections" type="button" value="Get Directions"&gt;&lt;/p&gt;
                  &lt;p style="border-top-style:solid;border-top-width:1px;margin-top:2em"&gt;&amp;nbsp;&lt;/p&gt;
                  &lt;p style="text-align:center;"&gt;&lt;input id="viewRoute" type="button" value="Zoom to Route"&gt;&lt;/p&gt;
                  &lt;p style="text-align:center;"&gt;&lt;input id="showSteps" type="checkbox" value="Show Steps"&gt; &lt;label for="ShowSteps"&gt;Show
                  Turns&lt;/label&gt;&lt;/p&gt;
                  &lt;p style="text-align:center;"&gt;&lt;input checked id="chkColor" name="chkDisplayColor" type="radio" value="landscape"&gt;Color &lt;input id=
                  "chkGreyscale" name="chkDisplayColor" type="radio" value="portrait"&gt;Grayscale&lt;/p&gt;
                  &lt;p style="text-align:center;"&gt;&lt;input checked id="chkOrientationLandscape" name="chkOrientation" type="radio" value=
                  "landscape"&gt;Landscape &lt;input id="chkOrientationPortrait" name="chkOrientation" type="radio" value=
                  "portrait"&gt;Portrait&lt;/p&gt;
                  &lt;p style="text-align:center;"&gt;&lt;label for="listPrintWhat"&gt;Print&lt;/label&gt; &lt;select id="listPrintWhat"&gt;
                      &lt;option selected value="both"&gt;
                          Both
                      &lt;/option&gt;
                      &lt;option value="map"&gt;
                          Map
                      &lt;/option&gt;
                      &lt;option value="directions"&gt;
                          Directions
                      &lt;/option&gt;
                  &lt;/select&gt; &lt;button id="btnPrintDirections" type="button"&gt;Print&lt;/button&gt;&lt;/p&gt;
              &lt;/div&gt;
          &lt;/div&gt;
              &lt;div id="printContainer"&gt;
                  &lt;div id="directions"&gt;&lt;/div&gt;
                  &lt;div class="map-landscape" id="map"&gt;&lt;/div&gt;
              &lt;/div&gt;
      &lt;/div&gt;
      &lt;script&gt;
        var map;
        var originMarker;
        var destinationMarker;
        var geocoder;
        var directionsService;
        var directionsDisplay;
        var stepDisplay;
        var myRoute;
        var MadisonAddress = "808 Farrish Madison, IL";
  
        // Create a new blank array for all the listing markers.
        var stepMarkers = [];
        var BWStyles = [{elementType: "labels.text.fill", stylers: [{color: "#000000"}]}, {elementType: "labels.text.stroke", stylers: [{color: "#ffffff"}, {weight: 2.5}]}, {featureType: "landscape", stylers: [{color: "#ffffff"}, {visibility: "on"}]}, {featureType: "landscape.man_made", stylers: [{color: "#ffffff"}]}, {featureType: "road", elementType: "geometry.fill", stylers: [{color: "#c0c0c0"}]}, {featureType: "road", elementType: "geometry.stroke", stylers: [{visibility: "off"}]}, {featureType: "road", elementType: "labels.text", stylers: [{color: "#000000"}]}, {featureType: "road", elementType: "labels.text.stroke", stylers: [{color: "#ffffff"}]}];
        var colorStyles = [{elementType: "labels.text.fill", stylers: [{color: "#000000"}]}, {elementType: "labels.text.stroke", stylers: [{color: "#ffffff"}, {weight: 2.5}]}, {featureType: "administrative.country", stylers: [{visibility: "off"}]}, {featureType: "administrative.land_parcel", stylers: [{visibility: "off"}]}, {featureType: "administrative.neighborhood", stylers: [{visibility: "off"}]}, {featureType: "administrative.province", elementType: "labels.text.fill", stylers: [{color: "#808080"}]}, {featureType: "administrative.province", elementType: "labels.text.stroke", stylers: [{visibility: "off"}]}, {featureType: "landscape", stylers: [{visibility: "simplified"}]}, {featureType: "landscape.natural", stylers: [{visibility: "off"}]}];
        //document.getElementById('steps').addEventListener("click", alert("Click"));
  
        function initMap() {
          // Constructor creates a new map - only center and zoom are required.
          map = new google.maps.Map(document.getElementById('map'), {
            center: {lat: 38.6838405, lng: -90.14422689999999}, // location of Madison Yard
            zoom: 13,
            mapTypeControl: false,
            styles: colorStyles
          });
  
          directionsService = new google.maps.DirectionsService;
          directionsDisplay = new google.maps.DirectionsRenderer({
            map: map,
            'preserveViewport': false,
            draggable: true,
            suppressMarkers: false,
            polylineOptions: {
              strokeColor: 'green',
              strokeWeight: 10,
              strokeOpacity: 0.5
            },
            panel: document.getElementById("directions")
            });
          directionsDisplay.addListener('directions_changed', showSteps);
          //stepDisplay = new google.maps.InfoWindow;
          geocoder = new google.maps.Geocoder();
          //document.getElementById('origin').addEventListener('change', getOrigin);
          //document.getElementById('destination').addEventListener('change', getDestination);
          document.getElementById('showSteps').addEventListener('click', showSteps);
          document.getElementById('chkColor').addEventListener('click', setStyle);
          document.getElementById('chkGreyscale').addEventListener('click', setStyle);
          document.getElementById('getDirections').addEventListener('click', calculateAndDisplayRoute);
          document.getElementById('viewRoute').addEventListener('click', routeZoom);
          document.getElementById("chkOrientationLandscape").addEventListener('change', changeOrientation);
          document.getElementById("chkOrientationPortrait").addEventListener('change', changeOrientation);
          document.getElementById("btnPrintDirections").addEventListener('click', printPage);
          document.getElementById("fromMadison").addEventListener('click', fromMadisonClick);
          document.getElementById("toMadison").addEventListener('click', toMadisonClick);
        }
  
        function fromMadisonClick() {
          document.getElementById('origin').value = MadisonAddress;
          getOrigin();
        }
  
        function toMadisonClick() {
          document.getElementById('destination').value = MadisonAddress;
          getDestination();
        }
  
        function printPage() {
          document.getElementById("printContainer").className = document.getElementById('listPrintWhat').value;
          window.print();
        }
  
        function setStyle() {
          if (document.getElementById('chkColor').checked)
            map.setOptions({styles: colorStyles});
          else
            map.setOptions({styles: BWStyles});
        }
  
        function changeOrientation() {
          var orientation = document.getElementsByName("chkOrientation");
          orientation.forEach(setOrientation);
        }
  
        function setOrientation(item) {
          var theMap = document.getElementById("map");
          if (item.checked)
            theMap.className = "map-" + item.value;
        }
  
        function getDestination() {
          if (typeof (destinationMarker) !== "undefined")
            destinationMarker.setMap(null);
          var address = document.getElementById('destination').value;
          geocoder.geocode({'address': address}, function (results, status) {
            if (status === 'OK') {
              map.setCenter(results[0].geometry.location);
              destinationMarker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location
              });
              google.maps.event.addListener(destinationMarker, 'click', function () {
                // Open an info window when the marker is clicked on, containing the text
                // of the step.
                stepDisplay = new google.maps.InfoWindow;
                populateInfoWindow(this, stepDisplay);
              });
              calculateAndDisplayRoute();
              routeZoom();
            } else {
              alert('Geocode was not successful for the following reason: ' + status);
            }
          });
        }
  
        function getOrigin() {
          if (typeof (originMarker) !== "undefined")
            originMarker.setMap(null);
          var address = document.getElementById('origin').value;
          geocoder.geocode({'address': address}, function (results, status) {
            if (status === 'OK') {
              map.setCenter(results[0].geometry.location);
              originMarker = new google.maps.Marker({
                map: map,
                position: results[0].geometry.location,
                title: "Origin"
              });
              calculateAndDisplayRoute();
            } else {
              alert('Geocode was not successful for the following reason: ' + status);
            }
          });
        }
  
        function routeZoom() {
          var bounds = new google.maps.LatLngBounds();
          bounds.extend(originMarker.getPosition());
          bounds.extend(destinationMarker.getPosition());
          //center the map to the geometric center of all markers
          map.setCenter(bounds.getCenter());
          map.fitBounds(bounds);
          //remove one zoom level to ensure no marker is on the edge.
          map.setZoom(map.getZoom());
          // set a minimum zoom 
          // if you got only 1 marker or all markers are on the same address map will be zoomed too much.
          if (map.getZoom() &gt; 15) {
            map.setZoom(15);
          }
        }
  
        function getNewRoute() {
          $.when(calculateAndDisplayRoute()).then(function () {
            showSteps();
          });
        }
  
  
        function calculateAndDisplayRoute() {
          directionsService.route({
          origin: document.getElementById('origin').value,
          destination: document.getElementById('destination').value,
          //waypoints: [{location: 'Adelaide, SA'}, {location: 'Broken Hill, NSW'}],
          travelMode: 'DRIVING',
          provideRouteAlternatives: false
          }, function(response, status) {
          if (status === 'OK') {
            directionsDisplay.setDirections(response);
            //deleteMarkers();
          }
          });
        }
  
        // Sets the map on all markers in the array.
        function setMapOnAll(map) {
          for (var i = 0; i &lt; stepMarkers.length; i++) {
            stepMarkers[i].setMap(map);
          }
        }
  
        // Removes the markers from the map, but keeps them in the array.
        function clearMarkers() {
          setMapOnAll(null);
        }
  
        // Shows any markers currently in the array.
        function showMarkers() {
          setMapOnAll(map);
        }
  
        // Deletes all markers in the array by removing references to them.
        function deleteMarkers() {
          clearMarkers();
          stepMarkers = [];
          //originMarker.setMap(null);
          //destinationMarker.setMap(null);
        }
  
        function showSteps() {
          // For each step, place a marker, and add the text to the marker's infowindow.
          // Also attach the marker to an array so we can keep track of it and remove it
          // when calculating new routes.
          // originMarker.setMap(null);
          deleteMarkers();
          myRoute = directionsDisplay.directions.routes[0].legs[0];
          //originMarker.setMap(null);
          stepCheck = document.getElementById('showSteps');
          if (stepCheck.checked) {
            for (var i = 0; i &lt; myRoute.steps.length; i++) {
              var marker = stepMarkers[i] = stepMarkers[i] || new google.maps.Marker({
                //if (i&gt;0) {
                //var marker = new google.maps.Marker({
                map: map,
                position: myRoute.steps[i].start_location,
                title: "Step " + (i),
                //animation: google.maps.Animation.DROP,
                id: i
              });
              google.maps.event.addListener(marker, 'click', function () {
                // Open an info window when the marker is clicked on, containing the text
                // of the step.
                stepDisplay = new google.maps.InfoWindow;
                stepDisplay.setContent(myRoute.steps[this.id].instructions);
                stepDisplay.open(map, this);
                //populateInfoWindow(this, stepDisplay);
              });
              // }
            }
          }
        }
  
        function makeInfoContent(instructions){
              var html = "&lt;div class=\"infoWindow\"&gt;" + instructions + "&lt;\/div&gt;";
              return(html);
                }
  
        // This function populates the infowindow when the marker is clicked. We'll only allow
        // one infowindow which will open at the marker that is clicked, and populate based
        // on that markers position.
        function populateInfoWindow(marker, infowindow) {
          // Check to make sure the infowindow is not already opened on this marker.
          if (infowindow.marker != marker) {
            // Clear the infowindow content to give the streetview time to load.
            infowindow.setContent('');
            infowindow.marker = marker;
            // Make sure the marker property is cleared if the infowindow is closed.
            infowindow.addListener('closeclick', function () {
              infowindow.marker = null;
            });
            var streetViewService = new google.maps.StreetViewService();
            var radius = 50;
            // In case the status is OK, which means the pano was found, compute the
            // position of the streetview image, then calculate the heading, then get a
            // panorama from that and set the options
            function getStreetView(data, status) {
              if (status === google.maps.StreetViewStatus.OK) {
                var nearStreetViewLocation = data.location.latLng;
                var heading = google.maps.geometry.spherical.computeHeading(
                        nearStreetViewLocation, marker.position);
                infowindow.setContent('&lt;div id="pano"&gt;&lt;\/div&gt;');
                var panoramaOptions = {
                  position: nearStreetViewLocation,
                  pov: {
                    heading: heading,
                    pitch: 0
                  }
                };
                var panorama = new google.maps.StreetViewPanorama(
                        document.getElementById('pano'), panoramaOptions);
              } else {
                infowindow.setContent('&lt;div&gt;' + marker.title + '&lt;\/div&gt;' +
                        '&lt;div&gt;No Street View Found&lt;\/div&gt;');
              }
            }
            // Use streetview service to get the closest streetview image within
            // 50 meters of the markers position
            streetViewService.getPanoramaByLocation(marker.position, radius, getStreetView);
            // Open the infowindow on the correct marker.
            infowindow.open(map, marker);
          }
        }
      &lt;/script&gt; 
  
      &lt;script async defer src=
      "https://maps.googleapis.com/maps/api/js?key=MyKey&amp;v=3&amp;callback=initMap"&gt;
      &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>