Here's how to do it:
Note: regarding the items and the button, replace the X by the pagenumber you are working on. And replace <your_key> by your Google Maps API key. You can obtain a key via https://developers.google.com/maps/documentation/javascript/tutorial
- Create the following procedure in the database:
create or replace PROCEDURE show_map (
p_map_div IN VARCHAR2 DEFAULT 'map-canvas', p_streetview_div IN VARCHAR2 DEFAULT 'pano', p_lat_item_name IN VARCHAR2
,p_lng_item_name IN VARCHAR2, p_yaw_item_name IN VARCHAR2, p_pitch_item_name IN VARCHAR2
,p_zoom_item_name IN VARCHAR2
)
IS
l_mapstr varchar2 (32000);
begin
l_mapstr := '
<script src="https://maps.googleapis.com/maps/api/js?key=<your_key>&sensor=false">
</script>
<script type="text/javascript">
var map;
var panorama;
var marker;
var streetview;
function initialize(myAddress, myLat, myLng, myPOV) {
var mapOptions = {zoom : 12
,mapTypeId : google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('||''''|| p_map_div ||''''||'),mapOptions);
panorama = new google.maps.StreetViewPanorama(document.getElementById('||''''||p_streetview_div||''''||'));
streetview = new google.maps.StreetViewService();
geocoder = new google.maps.Geocoder();
geocoder.geocode( { '||''''||'address'||''''||': myAddress}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var markerOptions = {map : map
,draggable : true
,animation : google.maps.Animation.DROP
,flat : false
,position : results[0].geometry.location
}
map.setCenter(results[0].geometry.location);
marker = new google.maps.Marker(markerOptions);
streetview.getPanoramaByLocation(results[0].geometry.location, 50, showStreetviewData);
google.maps.event.addListener(marker, '||''''||'dragstart'||''''||', function() {map.closeInfoWindow();} );
google.maps.event.addListener(marker, '||''''||'dragend'||''''||', function(event) {
document.getElementById("'||p_lat_item_name||'").value=event.latLng.lat();
document.getElementById("'||p_lng_item_name||'").value=event.latLng.lng();
streetview.getPanoramaByLocation(event.latLng, 50, showStreetviewData);
});
} else {
document.getElementById("'||p_map_div||'").innerHTML = "No mapdata found for given address. Did you enter a correct address?";
}
});
}
function showStreetviewData(data, status) {
if (status == google.maps.StreetViewStatus.OK) {
panorama.setPano(data.location.pano);
panorama.setPov({heading : 270
,pitch : 0
,zoom : 1
});
panorama.setVisible(true);
google.maps.event.addListener(panorama, '||''''||'position_changed'||''''||', function(event) {
var panoramaInfo = panorama.getPosition();
document.getElementById("'||p_lat_item_name||'").value=panoramaInfo.lat();
document.getElementById("'||p_lng_item_name||'").value=panoramaInfo.lng();
marker.setPosition(new google.maps.LatLng(panoramaInfo.lat(),panoramaInfo.lng()));
});
google.maps.event.addListener(panorama, '||''''||'pov_changed'||''''||', function(event) {
var panoInfo = panorama.getPov();
document.getElementById("'||p_pitch_item_name||'").value=panoInfo['||''''||'pitch'||''''||'];
document.getElementById("'||p_yaw_item_name||'").value=panoInfo['||''''||'heading'||''''||'];
document.getElementById("'||p_zoom_item_name||'").value=panoInfo['||''''||'zoom'||''''||'];
});
} else {
document.getElementById("'||p_map_div||'").innerHTML = "No Streetview data for this location?";
}
}
</script>';
--
sys.htp.p (l_mapstr);
EXCEPTION
WHEN OTHERS
THEN
raise_application_error (-20000, 'error in show_map: ' || SQLERRM);
END show_map;
A little explanation of the code:
This procedure uses a variable that holds Javascript code which is outputted by the sys.htp.p function. The procedure is called from the pl/sql region. The parameters are the name of the two divs where the google map and streetview panel are rendered, and the names of the items that hold the geo details, like latitude, longitude, yaw, pitch and zoom.
The code makes use of the Google api to find the latitude and the longitude for a given address. Furthermore is the code event-driven for the movement of the marker and the navigation through the streetview map. This recipe makes use of the Google maps api v3. Previously, this recipe used v2, which will be deprecated.
In the APEX builder, create an empty page.
Create 4 HTML regions. Call them Address details, Geo details, Google Map and Streetview map.
Click on the Geo details region and select 2 from the Column selectlist in the User Interface section. Click the apply changes button. Do the same for the Streetview map region.
Click on the Google map region and put the following code in the region source text area:
<div align="center" style="width: 100%; height: 300px;">
<div id="map_canvas" style="width: 500px; height: 300px"></div>
- Click apply changes
- Click on the streetview map region and put the following code in the region source text area:
<div id="pano" style="width: 500px; height: 300px"></div>
</div>
- Click apply changes
- Create the following items:
Region Address details:
- PX_ADDRESS
- PX_CITY
- PX_COUNTRY
Region Geo details:
- PX_LAT
- PX_LNG
- PX_YAW
- PX_PTCH
- PX_ZM
- In the buttons section, click the add button icon
- Select the address details region
- Select "create button among this region's items"
- Enter a name for the button, as well as a label. Click next
- Click next
- In the action selectlist, select "defined by dynamic action"
- In the execute validations selectlist, select no. click next
- Click create button
- In the dynamic actions section, click the add button
- Select advanced
- Wnter a name for the dynamic action, ie find_address. Click next
- In the event selectlist, select mouse button press
- In the selection type selectlist, select button
- In the button select list, select the button you just created
- Click next
- In the action selectlist, select "execute javascript code"
- In the code text area, enter the following code:
initialize(document.getElementById("PX_ADDRESS" ).value + "," + document.getElementById("PX_CITY" ).value + "," + document.getElementById("PX_COUNTRY" ).value,0,0,{yaw:0,pitch:0,zoom:0});
- Click next, click create
- Create a pl/sql region and enter the following code into the region source text area:
show_map('map_canvas','pano','PX_LAT','PX_LNG','PX_YAW','PX_PTCH','PX_ZM');
sys.htp.p('<script type="text/javascript">');
sys.htp.p('initialize('||''''||'Leidscheplein, Amsterdam,NL'||''''||','||0||','||0||',{yaw:'||0||',pitch:'||0||',zoom:'||0||'});');
sys.htp.p('</script>');
You can of course enter your own favourite address. In the User Interface section, select "No Template" in the Template select list. Click apply changes.
The page is ready now. The result should look something like this:
Try to move the red marker on the google map. You will see that the latitude and the longitude columns change and that the streetview changes. In the streetview map, click on the arrows on the road to navigate through the map. You will see that the red marker on the google map also moves and that the geo details change.
By the way, you can get the regions straight put next to one another and stacked by putting the following into the Region attributes text field in the Attributes section of the Address details and Geo details regions:
style="height:200px"