title: Disable google maps tile fading or detect if map is fully rendered?
body: <p><strong>Question</strong></p>
  
  <p>Is there a way to disable the fading of google maps tiles? Or is there a way to detect if a map is fully rendered?</p>
  
  <p><strong>Problem</strong></p>
  
  <p>I'd like to get an event when a map is fully loaded (and rendered) and take a screenshot. I tried these events as suggested in several answers</p>
  
  <pre><code>google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
    // screenshot
  });
  
  google.maps.event.addListener(map, 'idle', function(){
    // screenshot
  });
  
  window.onload = function(e){
    // screenshot
  };
  </code></pre>
  
  <p>but the tiles are still fading, even after all is loaded and the above mentioned events fired. </p>
  
  <p>It looks like this: left is google maps, right is an automated screenshot that is taken after the events fired:</p>
  
  <p><a href="https://i.stack.imgur.com/swBmz.jpg" rel="noreferrer"><img src="https://i.stack.imgur.com/swBmz.jpg" alt="enter image description here"></a></p>
  
  <p><strong>Code</strong></p>
  
  <p>The code is in html and JavaFX</p>
  
  <p>demo.html</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
  
      &lt;script src="http://maps.google.com/maps/api/js?sensor=false"&gt;&lt;/script&gt;
  
      &lt;style&gt;
        html, body {
          height: 100%;
          margin: 0;
          padding: 0;
        }
      #mapcanvas {
        /* height: 4000px; we need the value from java */
        width: 100%
      }
      &lt;/style&gt;
  
  
  &lt;/head&gt;
  &lt;body&gt;
  &lt;div id="mapcanvas"&gt;&lt;/div&gt;
  
  &lt;script type="text/javascript"&gt;
  
          console.log("Loading map tiles");
  
          // set map canvas height
          document.getElementById('mapcanvas').style.height = window.mapCanvasHeight;
  
          document.map = new google.maps.Map(document.getElementById("mapcanvas"));
  
          // the global window object is used to set variables via java
          var latlng = new google.maps.LatLng(window.lat, window.lon);
  
          // https://developers.google.com/maps/documentation/javascript/reference?hl=en
          var Options = {
              zoom: 17,
              center: latlng,
              mapTypeId: google.maps.MapTypeId.SATELLITE,
              disableDefaultUI: true,
          };
  
          var map = new google.maps.Map(document.getElementById("mapcanvas"), Options);
          document.goToLocation = function(x, y) {
  
              console.log("goToLocation, lat: " + x +", lon:" + y);
  
              var latLng = new google.maps.LatLng(x, y);
              map.setCenter(latLng);
  
          }
  
          // this doesn't work properly because some tiles fade in and hence you get a snapshot with faded tiles
          google.maps.event.addListenerOnce(map, 'tilesloaded', function(){
  
              console.log("tilesloaded");
  
              java.onMapLoadingFinished();
  
          });
  
          // This event is fired when the map becomes idle after panning or zooming.
          // it works after all tiles were first loaded and you zoom afterwards ( but doesn't work a 100% all the time )
          // initially you still get faded tiles
          google.maps.event.addListener(map, 'idle', function(){
  
              console.log("idle");
  
              // java.onMapLoadingFinished();
  
          });
  
          window.onload = function(e){
  
              console.log("window.onload");
  
              // java.onMapLoadingFinished();
  
          };
  
  &lt;/script&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>GoogleApp.java</p>
  
  <pre><code>import java.net.URL;
  
  import javafx.application.Application;
  import javafx.beans.value.ChangeListener;
  import javafx.concurrent.Worker.State;
  import javafx.scene.Scene;
  import javafx.scene.SnapshotParameters;
  import javafx.scene.control.ScrollPane;
  import javafx.scene.control.SplitPane;
  import javafx.scene.control.TextField;
  import javafx.scene.image.ImageView;
  import javafx.scene.image.WritableImage;
  import javafx.scene.layout.BorderPane;
  import javafx.scene.layout.Pane;
  import javafx.scene.paint.Color;
  import javafx.scene.web.WebEngine;
  import javafx.scene.web.WebView;
  import javafx.stage.Stage;
  import netscape.javascript.JSObject;
  
  /**
   * Load google maps map and take a snapshot from it
   */
  public class GoogleApp extends Application {
  
      // initial lat/lon
      double lat = 38.897676;
      double lon = -77.036483;
  
      double browserWidth = 1024; // this is set to 100% in the html css for the map canvas
      double browserHeight = 8000; // this is used in the html map canvas; IMPORTANT: when the app freezes during zoom in, then the problem is probably the height; it works without problems with height of e. g. 360
  
      MyBrowser webBrowser;
      TextField latitudeTextField;
      TextField longitudeTextField;
  
      private ScrollPane snapshotScrollPane;
  
      @Override
      public void start(Stage stage) throws Exception {
  
          webBrowser = new MyBrowser(browserWidth, browserHeight);
  
          ScrollPane browserScrollPane = new ScrollPane(webBrowser);
          snapshotScrollPane = new ScrollPane();
  
          SplitPane splitPane = new SplitPane(browserScrollPane, snapshotScrollPane);
  
          BorderPane borderPane = new BorderPane();
          borderPane.setCenter(splitPane);
          borderPane.setRight(snapshotScrollPane);
  
          Scene scene = new Scene(borderPane, 1024, 768);
          stage.setScene(scene);
          stage.show();
  
      }
  
      private void createSnapshot() {
  
          SnapshotParameters parameters = new SnapshotParameters();
          parameters.setFill(Color.TRANSPARENT);
  
          // new image from clipped image
          WritableImage wim = null;
          wim = webBrowser.snapshot(parameters, wim);
  
          snapshotScrollPane.setContent(new ImageView(wim));
      }
  
      public class JavaBridge {
  
          public void onMapLoadingFinished() {
  
              System.out.println("[javascript] onMapLoadingFinished");
  
              createSnapshot();
  
          }
  
          public void log(String text) {
              System.out.println("[javascript] " + text);
          }
  
      }
  
      private class MyBrowser extends Pane {
  
          WebView webView;
          WebEngine webEngine;
  
          public MyBrowser(double width, double height) {
  
              webView = new WebView();
              webView.setPrefWidth(width);
              webView.setPrefHeight(height);
  
              webEngine = webView.getEngine();
  
              webEngine.getLoadWorker().stateProperty().addListener((ChangeListener&lt;State&gt;) (observable, oldState, newState) -&gt; {
  
                  System.out.println("[State] " + observable);
  
                  if (newState == State.SCHEDULED) {
  
                      System.out.println("Webpage loaded");
  
                      // inject "java" object
                      JSObject window = (JSObject) webEngine.executeScript("window");
                      JavaBridge bridge = new JavaBridge();
                      window.setMember("java", bridge);
  
                      // console.log
                      webEngine.executeScript("console.log = function(message)\n" + "{\n" + "    java.log(message);\n" + "};");
  
                      // initialize variables
  
                      // canvas height
                      webEngine.executeScript("window.mapCanvasHeight = '" + browserHeight + "px'");
  
                      System.out.println("Latitude = " + lat + ", Longitude = " + lon);
  
                      webEngine.executeScript("window.lat = " + lat + ";" + "window.lon = " + lon + ";");
  
                  }
  
                  if (newState == State.SUCCEEDED) {
                      // createSnapshot();
                  }
              });
  
              // logging other properties
              webEngine.getLoadWorker().exceptionProperty().addListener((ChangeListener&lt;Throwable&gt;) (ov, t, t1) -&gt; System.out.println("[Exception] " + t1.getMessage()));
              webEngine.getLoadWorker().progressProperty().addListener((ChangeListener&lt;Number&gt;) (observable, oldState, newState) -&gt; System.out.println( "[Progress] " + newState));
              webEngine.getLoadWorker().workDoneProperty().addListener((ChangeListener&lt;Number&gt;) (observable, oldState, newState) -&gt; System.out.println( "[WorkDone] " + newState));
              webEngine.getLoadWorker().runningProperty().addListener((ChangeListener&lt;Boolean&gt;) (observable, oldState, newState) -&gt; System.out.println( "[Running] " + newState));
              webEngine.getLoadWorker().messageProperty().addListener((ChangeListener&lt;String&gt;) (observable, oldState, newState) -&gt; System.out.println( "[Message] " + newState));
  
  
              final URL urlGoogleMaps = getClass().getResource("demo.html");
              webEngine.load(urlGoogleMaps.toExternalForm());
  
              // TODO: how should that work? it doesn't do anything when we invoke an alert
              webEngine.setOnAlert(e -&gt; System.out.println("Alert: " + e.toString()));
  
              getChildren().add(webView);
  
          }
  
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>
  
  <p>console output</p>
  
  <pre><code>[WorkDone] 0.0
  [Progress] 0.0
  [State] ReadOnlyObjectProperty [bean: javafx.scene.web.WebEngine$LoadWorker@6954b271, name: state, value: SCHEDULED]
  Webpage loaded
  Latitude = 38.897676, Longitude = -77.036483
  [Running] true
  [State] ReadOnlyObjectProperty [bean: javafx.scene.web.WebEngine$LoadWorker@6954b271, name: state, value: RUNNING]
  [WorkDone] 50.0
  [Progress] 0.5
  [WorkDone] 66.66666666666667
  [Progress] 0.6666666666666667
  [WorkDone] 76.59016927083334
  [Progress] 0.7659016927083334
  [javascript] Loading map tiles
  [WorkDone] 79.69424280262338
  [Progress] 0.7969424280262337
  [WorkDone] 82.91479192680356
  [Progress] 0.8291479192680357
  [WorkDone] 86.13534105098375
  [Progress] 0.8613534105098376
  [WorkDone] 87.9566062307981
  [Progress] 0.879566062307981
  [WorkDone] 89.554165026828
  [Progress] 0.89554165026828
  [WorkDone] 89.62836770069038
  [Progress] 0.8962836770069037
  [javascript] idle
  [WorkDone] 89.70492380394815
  [Progress] 0.8970492380394814
  [WorkDone] 89.78964107398804
  [Progress] 0.8978964107398804
  [WorkDone] 89.85311355504936
  [Progress] 0.8985311355504936
  [WorkDone] 89.91528395017954
  [Progress] 0.8991528395017955
  [WorkDone] 89.9528416875862
  [Progress] 0.899528416875862
  [javascript] window.onload
  [Message] Loading complete
  [WorkDone] 100.0
  [Progress] 1.0
  [State] ReadOnlyObjectProperty [bean: javafx.scene.web.WebEngine$LoadWorker@6954b271, name: state, value: SUCCEEDED]
  [Running] false
  [javascript] tilesloaded
  [javascript] onMapLoadingFinished
  taking screenshot
  </code></pre>
  
  <p>Of course one could wait a second and take the screenshot then, but that's not a proper solution.</p>