Skip to content

How it works ​

The component works in a simple way: it creates an HTML page with some JavaScript functions inside it, loads it in the browser, and then calls those functions with ExecuteScript whenever one of its methods is called.

If you want to look at the page, put a breakpoint in TEdgeGoogleMapViewer.ShowMap and read the HTML that is handed to the browser.

From a method to a JavaScript function ​

Look at GotoAddress:

pascal
procedure TEdgeGoogleMapViewer.GotoAddress(const Address: string);
var
  ScriptCommand: String;
begin
  FAddress := Address;
  if FAddress = '' then
    HideMap
  else if not MapVisible then
    ShowMap(FAddress)
  else
  begin
    ScriptCommand := Format('codeAddress(%s)', [JSQuotedStr(ClearAddressText(Address))]);
    ExecuteScript(ScriptCommand);
  end;
end;

codeAddress is a function of the page that asks Google's geocoder for the position and puts a marker there. The text of the address reaches the script through JSQuotedStr, which turns it into a JavaScript string literal: quotes, backslashes, control characters and </script> are escaped.

Adding your own JavaScript ​

Anything the Google Maps JavaScript API can do, you can add. The page is assembled in GetHTMLScript from the functions of the component:

pascal
function TEdgeGoogleMapViewer.GetHTMLScript: string;
var
  LJSScript: string;
begin
  LJSScript := GetJSVariables + sLineBreak +
    GetJSInitialize + sLineBreak +
    (...)
    GetJSRouteAddress + sLineBreak +
    GetJSCalcRoute;
  if Assigned(FOnGetJavascript) then
    FOnGetJavascript(Self, LJSScript);
  Result :=
    '<script type="text/javascript"> ' + sLineBreak +
    LJSScript + sLineBreak +
    '</script> ' + sLineBreak;
end;

There are two ways to extend it:

  • The OnGetJavascript event receives the whole script in a var parameter: add your functions to it, then call them with ExecuteScript.
  • A descendant of the component: the GetHTML... functions and most of the GetJS... ones are virtual. Override the one you need, or add a function to GetHTMLScript.
pascal
procedure TMainForm.EdgeGoogleMapViewerGetJavascript(ASender: TObject;
  var AJavascript: string);
begin
  AJavascript := AJavascript + sLineBreak +
    'function ZoomToWorld() { map.setZoom(2); }';
end;

// ... later
EdgeGoogleMapViewer.ExecuteScript('ZoomToWorld()');

OnGetHTMLBody does the same for the body of the page, for example to add a panel next to the map.

A script of yours can send a message to Delphi with window.chrome.webview.postMessage(...): the messages the component does not know about arrive in OnWebUnhandledMessageReceived.

See the Google Maps JavaScript API reference for what is available, and please make a pull request to the project if you add something that can be useful to everybody.

The page and the Google Maps API ​

The Google Maps API is loaded by the page from Google's servers, asynchronously, with the geometry and marker libraries, using the key you registered. So the map needs the internet, and the key is visible to anybody who can inspect the page: restrict it in the Google console.

The component waits for the page to tell that the map is ready (with a safety limit of 15 seconds) before it draws on it, which is why the Put... methods can be called right after GotoAddress, even when the map was hidden.

Released under the Apache License 2.0