题
有没有办法禁用谷歌地图瓷砖的褪色?或者有没有办法检测地图是否完全渲染?
问题
我想在地图完全加载(和渲染)时获取一个事件并截取屏幕截图.我按照几个答案的建议尝试了这些事件
google.maps.event.addListenerOnce(map, 'tilesloaded', function(){ // screenshot }); google.maps.event.addListener(map, 'idle', function(){ // screenshot }); window.onload = function(e){ // screenshot };
但即使在加载并且上述事件被触发后,瓷砖仍在褪色.
它看起来像这样:左边是谷歌地图,右边是在事件发生后拍摄的自动截图:
码
代码在html和JavaFX中
demo.html
GoogleApp.java
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) (observable, oldState, newState) -> { 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 ) (ov, t, t1) -> System.out.println("[Exception] " + t1.getMessage())); webEngine.getLoadWorker().progressProperty().addListener((ChangeListener ) (observable, oldState, newState) -> System.out.println( "[Progress] " + newState)); webEngine.getLoadWorker().workDoneProperty().addListener((ChangeListener ) (observable, oldState, newState) -> System.out.println( "[WorkDone] " + newState)); webEngine.getLoadWorker().runningProperty().addListener((ChangeListener ) (observable, oldState, newState) -> System.out.println( "[Running] " + newState)); webEngine.getLoadWorker().messageProperty().addListener((ChangeListener ) (observable, oldState, newState) -> 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 -> System.out.println("Alert: " + e.toString())); getChildren().add(webView); } } public static void main(String[] args) { launch(args); } }
控制台输出
[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
当然,人们可以等一下然后拍摄截图,但这不是一个合适的解决方案.