I am trying to add a column next to GE that has a list of all the Placemarks, as links or buttons, and when you click on those links it will exit the tour and jump to (or flyto) that placemark's location and pop-up the balloon.
the KML has a list of FlyTo's and LookAt's inside of a tour as well as Placemarks inside a document :).
Here is an Example of my KML placemark:
<Placemark id="Mussorie">
<name>Karen Snyder</name>
<description>
Karen Snyder is an Arts Specialist learning language and culture through the arts in Mussorie, India
</description>
<styleUrl>#Icon</styleUrl>
<Point>
<coordinates>79.134521,30.040566,0</coordinates>
</Point>
</Placemark>
Here is my JavaScript and HTML:
<html>
<head>
<title>Shepherd Global Outreach Partners</title>
<script src="https://www.google.com/jsapi"> </script>
<script src="http://earth-api-samples.googlecode.com/svn/trunk/lib/kmldomwalk.js" type="text/javascript"> </script>
<script type="text/javascript">
var ge;
var tour;
var curr_pm;
var obj_pm;
var linksit='';
var linksitcount=1;
var links = [];
google.load("earth", "1");
function init() {
var urlquery = location.href.split("?");
if(urlquery[1]) {
var urlterms = urlquery[1].split(",");
curr_pm = urlterms[0];
}
google.earth.createInstance('map3d', initCB, failureCB);
}
function initCB(instance) {
ge = instance;
ge.getWindow().setVisibility(true);
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, true);
var href = 'http://www.shepnet.org/GO.kml?ID='+Math.floor((Math.random()*100000)+1) ;
google.earth.fetchKml(ge, href, fetchCallback);
function fetchCallback(fetchedKml) {
// Alert if no KML was found at the specified URL.
if (!fetchedKml) {
setTimeout(function() {
alert('Bad or null KML');
}, 0);
return;
}
// Add the fetched KML into this Earth instance.
ge.getFeatures().appendChild(fetchedKml);
// Walk through the KML to find the tour object; assign to variable 'tour.'
walkKmlDom(fetchedKml, function() {
if (this.getType() == 'KmlTour') {
tour = this;
return false;
}
});
if (tour) {
ge.getTourPlayer().setTour(tour);
ge.getTourPlayer().play();
ge.getTourPlayer().setLoop(true)
}
if (!fetchedKml) {
// wrap alerts in API callbacks and event handlers
// in a setTimeout to prevent deadlock in some browsers
setTimeout(function() {
alert('Bad or null KML');
}, 0);
return;
}
// Show the entire KML file in the plugin.
currentKmlObject = fetchedKml;
ge.getFeatures().appendChild(currentKmlObject);
//Walk the DOM looking for a KmlLineString - the Race Path
var links = [];
walkKmlDom(fetchedKml, function() {
if (this.getType() == 'KmlPlacemark') {
// create a link to the placemark
links.push('<a href="javascript:void(0);" onclick="flyto(\'' + this.getUrl() + '\')"> ' + this.getName() + ' </a><br>');
}});
for (index = 0; index < links.length; ++index) {
console.log(links[index]);
}
}
}
var flyto = function(url) {
// close any currently open balloon.
ge.setBalloon(null);
// find the placemark from the url parameter
var placemark = ge.getElementByUrl(url);
if(placemark == null) {
console.log("Placemark is null: " + url);
return;
}
// create a lookat based on that feature's geometry
var lookAt = ge.createLookAt('');
lookAt.setLatitude(placemark.getGeometry().getLatitude());
lookAt.setLongitude(placemark.getGeometry().getLatitude())
// Update the view in Google Earth using the lookat
ge.getView().setAbstractView(lookAt);
// open the feature's balloon
ge.setBalloon(placemark.getBalloon());
}
function failureCB(errorCode) {
}
function UCLA() {
ge.getTourPlayer().reset();
var camera = ge.getView().copyAsCamera(ge.ALTITUDE_RELATIVE_TO_GROUND);
camera.setLatitude(34.0688272174651);
camera.setLongitude(-118.445067424559);
camera.setAltitude(10000);
ge.getView().setAbstractView(camera);
}
function pauseTour() {
window.open(href = 'http://www.shepnet.org/GO.kml#UCLA');
}
function resetTour() {
ge.getTourPlayer().reset();
}
function exitTour() {
ge.getTourPlayer().setTour(null);
}
google.setOnLoadCallback(init);
</script>
</head>
<body>
<div id="map3d" style="height: 768px; width: 1280px;"></div>
<div id ="controls">
<input type="button" onClick="flyto('http://www.shepnet.org/GO.kml#UCLA')" value="UCLA"/>
<input type="button" onClick="resetTour()" value="Stop/Reset Tour"/>
<input type="button" onClick="exitTour()" value="Exit Tour"/>
<a href="javascript:void(0);" onClick="flyto('http://www.shepnet.org/GO.kml#Mussorie')"> 'Mussorie' </a>
</div>
</body>
</html>
You can modify your current walkKmlDom
implementation as that is already walking the kml dom and checking for Placemarks. i.e.
walkKmlDom(fetchedKml, function() {
if (this.getType() == 'KmlPlacemark' && this.getID().toLowerCase() == curr_pm.toLowerCase()) {
obj_pm = this;
return false; // stop the DOM walk here.
}
Simply use that to build a list of links to the placemarks. You can use getUrl
on the placemark object to do this. See https://developers.google.com/earth/documentation/accessors
var links = [];
walkKmlDom(fetchedKml, function() {
if (this.getType() == 'KmlPlacemark') {
// create a link to the placemark
links.push('<a href="javascript:void(0);" onclick="flyto(' + this.getUrl() + ')"> ' + this.getName() + ' </a>');
// rest of your current conditional logic here
// if(this.getID().toLowerCase()) etc..
}
}
// do something with links...
for (index = 0; index < links.length; ++index) {
console.log(links[index]);
}
Then you need to implement the flyto
helper function to actually fly to the locations and open the balloons when the links are clicked. Something like the following should work.
var flyto = function(url) {
// close any currently open balloon.
ge.setBalloon(null);
// find the placemark from the url parameter
var placemark = ge.getElementByUrl(url);
if(placemark == null) {
console.log("Placemark is null: " + url);
return;
}
// create a lookat based on that feature's geometry
var lookAt = ge.createLookAt('');
lookAt.setLatitude(placemark.getGeometry().getLatitude());
lookAt.setLongitude(placemark.getGeometry().getLatitude())
// Update the view in Google Earth using the lookat
ge.getView().setAbstractView(lookAt);
// open the feature's balloon
ge.setBalloon(placemark.getBalloon());
}