2017-02-05 3 views
-1

Jetzt auf der google.com/maps-Seite, wenn ich auf den Namen/das Label eines Landes oder einer Stadt klicke, wird dieser Bereich hervorgehoben und öffnet das linke Popup-Fenster mit Informationen.Anklickbare Ortsbeschriftungen in Google Map API

Ist es möglich, dasselbe mit der Google Maps API zu realisieren? Um die Beschriftung bei Mouseover zu markieren, markieren Sie die Grenzen von Land, Bundesland oder Stadt, indem Sie auf klicken und in js nach Name/Name des Benutzers auswählen.

Ich schaute Google Maps API JavaScript-Dokumentation, aber ähnliche Funktionalität nicht gefunden.

Danke!


Sorry für unpräzise Frage.

Gibt es eine Möglichkeit, klickbare Land/Stadt-Namen auf der Karte mit API zu setzen, wie auf google.com/maps Seite?

+1

sicher, es ist möglich, aber Sie müssen, da kein Kommentar eine Datenquelle für Grenzen – charlietfl

+0

upvoted für Downvoting – Datadimension

+0

@DataMechanics Abstimmung ist anonym von Entwurf hier – charlietfl

Antwort

0

Empfehlen Sie eine Barebone-GMap-Klasse. Wie ich es passiert bin gerade diese wieder besuchen mich so diesen Code versuchen (es könnte einige Änderungen benötigen)

/** 
* 'GMap' 
* extends googlemaps to allow simpler coding in other apps, should be loaded after the main google maps 
* a new instance of a google map is contructed calling this with identical arguments to the standard class and then returned 
* the map name must be unique and reserved as a global by the client code, eg var pagemap outside of function, so the external callbacks 
* can use this name to run a function against, eg pagemap.queryMove_do 
* 
*/ 

function GMap(mapId, options) { 
    this.name = null; 
    this.map = null; 
    this.bounds = null; //view point boundary 
    this.gui_reg; 
    this.mapoptions; 
    this.calledbackonload; 
    this.polygons = {}; 
    this.lngoffset = {'direction': '', referenceelem: ''}; 
    this.infowindows = {}; 
    this.infowindowindex = 0; 
    GMap.prototype.__construct = function (mapId, options) { 
    var mapbuffer = new Data_buffer(); //this has to be vague as 3rd party api data is not always the same format, simply return data to the logged map interface objects 

    if (typeof window.MAP_INTERFACE_CTRL === 'undefined') {//if not created, global constant to co-ordinate ajax requests with map objects and 3rd party API, and allow funneling back to local objects 
     window.MAP_INTERFACE_CTRL = new Data_buffer(); //this has to be vague as 3rd party api data is not always the same format, simply return data to the logged map interface objects 
    } 
    options.panControlOptions = model.array_defaults(
      options.ctrlcfg, 
      { 
       position: google.maps.ControlPosition.RIGHT_BOTTOM 
      } 
    ); 
    options.zoomControlOptions = model.array_defaults(
      options.ctrlcfg, 
      { 
       position: google.maps.ControlPosition.RIGHT_CENTER 
      } 
    ); 
    this.mapoptions = model.array_defaults(
      options, 
      { 
       center: new google.maps.LatLng(54.5, -7), 
       zoom: 6, 
       minzoom: 15, 
       maxzoom: 21 
      } 
    ); 
    this.gui_reg = {location: {address: new Array()}}; 
    this.name = mapId; 
    this.map = new google.maps.Map(document.getElementById(mapId), this.mapoptions); 
    var selfobj = this; 
    google.maps.event.addListener(//processes client registration for registered events 
      this.map, 
      'dragend', //center changed causes too many requests 
      function() { 
       selfobj.update_client_go("location"); 
      } 
    ); 
//create invisible scratchpad 
    if ($('#map_pool').length == 0) { 
     $('body').append("<div id='map_pool'></div>"); 
     $('#map_pool').hide(); 
    } 
    /* 
    callback_obj = this; 
    google.maps.event.addListener(this.map, 'tilesloaded', function(evt) { 
    callback_obj.map.setZoom(9); 
    });*/ 
    } 

    /*****************************************************************/ 
    /* METHODS FOR BOTH GMAP AND CLIENT */ 
    /*****************************************************************/ 

    /* 
    * defines offset of mapcentre away from an element such as custom controls 
    * which overlay a large amount of map 
    * positive or negative according to offset direction where the element might be on the 
    * left or the right 
    */ 
    GMap.prototype.set_lng_offset = function (elemid, dir) { 
    var direction = 'right'; 
    if (dir == 'left') { 
     direction = dir; 
    } 
    this.lngoffset = {direction: direction, referenceelem: elemid}; 
    } 

    /* 
    * returns lng offset according to definitions and current map situation 
    */ 
    GMap.prototype.calc_lng_offset = function() { 
//get lng width of map 
    var eastlng = this.map.getBounds().getNorthEast().lng(); 
    var westlng = this.map.getBounds().getSouthWest().lng(); 
    var lngspan; 
    if (westlng <= 0 && eastlng >= 0) { 
     lngspan = Math.abs(westlng) + eastlng; 
    } else if (westlng >= 0 && eastlng <= 0) { 
     lngspan = (180 - westlng) + (180 - Math.abs(eastlng)); 
    } else if (westlng < 0 && eastlng < 0) { 
     lngspan = Math.abs(eastlng) + westlng; 
    } else { 
     lngspan = eastlng - westlng; 
    } 

//get px width of map and referenced element 
    var mapwidth = $("#" + this.name).width(); 
    var offsetpx = $("#" + this.lngoffset.referenceelem).width(); 
    //convert this px to lng offset for map by multiplying by lngpx 
    var lngperpx = lngspan/mapwidth; //calc lng/px as lngpx 
    //calc the offset lng 
    var offsetlng = offsetpx * lngperpx; 
    if (this.lngoffset.direction == 'left') { 
     var offsetlng = 0 - offsetlng; 
    } 
    return offsetlng; 
    } 

    /* 
    * returns an object with north south east west and centre coordinates of the current view 
    * args.precision states number of figures after decimal returned - if not give a full result is returned. 
    * @returns {float north,float east,float south,float west,float lat,float lng} 
    */ 
    GMap.prototype.get_viewport_coords = function (args) { 
    if (args == undefined) { 
     args = {}; 
    } 
    var coords = {}; 
    coords.north = this.map.getBounds().getNorthEast().lat(); 
    coords.east = this.map.getBounds().getNorthEast().lng(); 
    coords.south = this.map.getBounds().getSouthWest().lat(); 
    coords.west = this.map.getBounds().getSouthWest().lng(); 
    coords.lat = this.map.getCenter().lat(); 
    coords.lng = this.map.getCenter().lng(); 
    if (args.precision != undefined) { 
     coords.north = coords.north.toFixed(args.precision); 
     coords.east = coords.east.toFixed(args.precision); 
     coords.south = coords.south.toFixed(args.precision); 
     coords.west = coords.west.toFixed(args.precision); 
    } 
    return coords; 
    } 

    /* 
    * 'map_query' 
    * takes a text query and queries to google for info 
    * 
    * required due to APIs not being the same, a uuid is registered globally and a global process used to redirect 
    * because of this the global process must identify a map object by UUID and only expect a single argument as an object literal (JSON) 
    * this is then passed back to the object that initiated the ajax or UUID request 
    * 
    * @param OBJECT query_cfg to send to gmap geocode 
    *  @param string query_cfg.type states what type of query and what action to take, allowing multiple use for this method 
    *  @param string query_cfg.query_data a string containing address data such as '<postcode>, <street>, <property>' 
    *  @param string query_cfg.callback to return the data to 
    */ 
    GMap.prototype.geo_query = function (query_cfg) { 

//package pre query data and set defaults if not set 
    query_cfg = model.array_defaults(
      query_cfg, 
      { 
       clientid: this.name, 
       callback: 'update_client_do'//client code can set its own callback,else set callback to this 
      } 

    ); 
    var geo_queryid = MAP_INTERFACE_CTRL.callback_push(query_cfg); 
    switch (query_cfg.type) { 
     case "location"://returns location data at given lat lng coords 
     var gcoder = new google.maps.Geocoder(); 
     gcoder.geocode({'location': {lat: query_cfg.lat, lng: query_cfg.lng}}, function (results, status) { 
      var server_response = {results: results, status: status}; 
      eval("MAP_INTERFACE_CTRL.callback_pop('" + geo_queryid + "',server_response)"); 
     }); 
     break; 
     case "address_latlng": 
     var gcoder = new google.maps.Geocoder(); 
     gcoder.geocode({'address': query_cfg.query_data}, function (results, status) { 
      var server_response = {results: results, status: status}; 
      eval("MAP_INTERFACE_CTRL.callback_pop('" + geo_queryid + "',server_response)"); 
     }); 
     break; 
     case "sv_pano_latlng"://gets streetview pano for given lat lng 
     var sv_service = new google.maps.StreetViewService(); 
     sv_service.getPanoramaByLocation(query_cfg.latlng, query_cfg.radius, function (results, status) { 
      var server_response = {results: results, status: status}; 
      eval("MAP_INTERFACE_CTRL.callback_pop('" + geo_queryid + "',server_response)"); 
     }); 
     break; 
     case "viewport_range"://returns lat lng for viewport and centre to callback 
     var gcoder = new google.maps.Geocoder(); 
     var bounds = this.bounds; 
     var center = this.map.getCenter(); 
     gcoder.geocode({address: change_request}, function (results, status) { 
      callback_obj.viewport_range_do(results, status) 
     }); 
     break; 
    } 
    } 

    /* 
    * 'formatted_geo_result' 
    * interprets geocoded results to a standard uniform independent of map api 
    * @param OBJECT geo_result data returned (in this map interface from google) 
    */ 
    GMap.prototype.formatted_geo_result = function (geodata) { 
    var formatted = {}; 
    var itemdefaults = { 
     address: '', 
     lat: null, 
     lng: null 
    } 
    for (var i in geodata.results) { 
     var item = { 
     address: geodata.results[i].formatted_address, 
     lat: geodata.results[i].geometry.location.lat(), 
     lng: geodata.results[i].geometry.location.lng(), 
     } 
     formatted[i] = model.array_defaults(item, itemdefaults); 
    } 
    return formatted; 
    } 
    /* 
    * 'map_change' 
    * takes a request and processes and changes map accordingly 
    * 
    * callerobj is optional, if not given then callback will be back to this map object 
    * if a callerobj is given this must be to an object which can accept it 
    * (if callerobj is a top level function it needs to pass the object as keyword window - not 'window') 
    * The callback method is named as query type with _do appended eg address_move_do 
    * Some query types require the caller object to handle the query and DO NOT have a method defined in the map object 
    * If this map object DOES have the callback but a callback_obj is given then it will override this map object 
    * 
    * @param string change_request free text to send to gmap object 
    * @param string change_type states what type of query and what action to take, allowing multiple use for this method 
    * @param string callback function to run on change completion. 
    */ 
    GMap.prototype.map_change = function (change_type, change_data, callback) { 
    switch (change_type) { 
     case "lat_lng": 
     this.map.panTo({lat: change_data.latlng.lat, lng: change_data.latlng.lng + this.calc_lng_offset()}); 
     break; 
     case "address"://to address_latlng as translation for this map object 
     this.geo_query({type: "address_latlng", clientid: this.name, callback: "map_change_do", change_type: change_type, query_data: change_data}); 
     break; 
    } 
    if (callback != undefined) { 
     this.loadedCallback(callback); 
    } 
    } 

    /* 
    * 'map_change_do' 
    * processes any ajax return required by map_change 
    * 
    * @param string change_request free text to send to gmap object 
    * @param string change_type states what type of query and what action to take, allowing multiple use for this method 
    */ 
    GMap.prototype.map_change_do = function (pre_data, callback_data) { 
    switch (pre_data.change_type) { 
     case "address": 
     this.map_change("lat_lng", {latlng: {lat: callback_data.results[0].geometry.location.lat(), lng: callback_data.results[0].geometry.location.lng()}}); //callback_data.results[0].geometry.location.lat() 
     break; 
    } 
    } 

    /* 
    * permanently deletes all objects such as map markers (pins) etc 
    */ 
    GMap.prototype.clearmapobjects = function() { 
    this.map.clearMarkers(); 
    } 

    GMap.prototype.panotestA = function() { 
    var locquery = "framlingham tech centre"; 
    this.map_change("address", locquery); 
    this.map.setZoom(20); 
    this.geo_query("location", locquery) 
    this.geo_query({type: "address_latlng", clientid: this.name, callback: "panotestB", query_data: locquery}); 
    } 
    GMap.prototype.panotestB = function (pre_data, callback_data) { 
    var pin = this.add_pin(callback_data.results[0].geometry.location.lat(), callback_data.results[0].geometry.location.lng(), {infopop: {content: 'hello', streetview: true}}); 
    } 
    /* 
    * 'add_pin' 
    * adds a pin to a map 
    * 
    * @param float lat is latitude position 
    * @param float lng is longitude position 
    * @param object info_args other pin constructs such as the info displayed while clicking it 
    * @return object marker 
    */ 
    GMap.prototype.add_pin = function (lat, lng, info_args) { 
    info_args = model.array_defaults(
      info_args, 
      { 
       width: 16, 
       height: 16, 
       animation: google.maps.Animation.DROP, 
       icon: { 
       url: "http://" + ROOTUC + "//css/images/icons/ROYOdot_a.gif" 
       }, 
       infopop: null 
      } 
    ); 
    /* 
    var icon = { 
    url: info_args.icon.url, 
    size: new google.maps.Size(20, 20), 
    origin: new google.maps.Point(0, 0), 
    anchor: new google.maps.Point(0, 0) 
    }; 
    */ 
    var iconImage = new google.maps.MarkerImage(
      info_args.icon.url, // url to image inc http:// 
      null, // desired size 
      null, // offset within the scaled sprite 
      null, // anchor point is half of the desired size 
      new google.maps.Size(info_args.width, info_args.height) // required size 
      ); 
    var pin = new google.maps.Marker({ 
     position: new google.maps.LatLng(lat, lng), 
     map: this.map, 
     title: info_args.label, 
     icon: iconImage, 
     optimized: false, //to allow for animations 
     animation: info_args.animation, 
    }); 

    if (info_args.infopop != null) { 
     /*content is forced into div with black font as google default 
     * is white text on white background ?!?!?! 
     */ 

     info_args.infopop = model.array_defaults(
       info_args.infopop, 
       { 
       fontcolor: '#000000', 
       infowidth: '40em', 
       streetview: false 
       }); 
     //standard google defs 
     var infowindow = new google.maps.InfoWindow(); 
     //extra seperate data ref for client apps 
     infowindow.metadata = { 
     parent: this, 
     parentid: this.infowindowindex, 
     }; 
     this.infowindows[this.infowindowindex] = { 
     infowidth: info_args.infopop.infowidth, 
     content: info_args.infopop.content, 
     fontcolor: info_args.infopop.fontcolor, 
     latlng: {lat: lat, lng: lng}, 
     streetview: info_args.infopop.streetview 
     }; 
     this.infowindowindex++; 

     //build for pin click 
     google.maps.event.addListener(pin, 'click', function() { 
     var infodata = infowindow.metadata.parent.infowindows[infowindow.metadata.parentid]; 

     //build content 
     var infocontent = "<div id='" + infowindow.metadata.parent.name + "infowindow" + (infowindow.metadata.parentid) + "' style='color:" + infodata.fontcolor + ";width:" + infodata.infowidth + "'>"; 
     infocontent += infodata.content; 
     if (infodata.streetview) { 
      infocontent += "<div id='" + infowindow.metadata.parent.name + "infowindowsvframe" + (infowindow.metadata.parentid) + "' class='infostreetviewframe' >"; 
      infocontent += ". . . loading view</div>"; 
     } 
     infocontent += "</div>"; 
     infowindow.setContent(infocontent); 
     infowindow.open(this.map, pin); 
     if (infodata.streetview) { 
      var service = new google.maps.StreetViewService(); 
      infowindow.metadata.parent.geo_query({type: "sv_pano_latlng", latlng: infodata.latlng, radius: 50, clientid: infowindow.metadata.parent.name, streetviewframe: infowindow.metadata.parent.name + "infowindowsvframe" + (infowindow.metadata.parentid), callback: "add_streetview_do"}); 
     } 
     }); 
    } 
    } 

    /* 
    * 'add_streetview' 
    * for flexibility addition of a streetview into a named dom element id 
    * 
    * @param object args 
    *  @param.args string elemid the element to put the streetview into 
    * 
    */ 
    GMap.prototype.add_streetview_do = function (predata, callbackdata) { 
    var svelement = document.getElementById(predata.streetviewframe); 
    if (callbackdata.status == google.maps.StreetViewStatus.OK) { 
     var targetPOVlocation = predata.latlng 
     var svLatLng = {lat: callbackdata.results.location.latLng.lat(), lng: callbackdata.results.location.latLng.lng()}; 

     // var svLatLng = new google.maps.LatLng(callbackdata.results.location.latLng.lat(), callbackdata.results.location.latLng.lng()); 

     //var svLatLng = callbackdata.results.location.latLng; 

     var povyaw = this.getBearing(svLatLng, targetPOVlocation); 
     var sv = new google.maps.StreetViewPanorama(svelement); 
     var svoptions = { 
     position: svLatLng, 
     addressControl: false, 
     linksControl: false, 
     panControl: false, 
     zoomControlOptions: { 
      style: google.maps.ZoomControlStyle.SMALL 
     }, 
     pov: { 
      heading: povyaw, 
      pitch: 10, 
      zoom: 1 
     }, 
     enableCloseButton: false, 
     visible: true 
     }; 
     sv.setOptions(svoptions); 
    } else { 
     svelement.innerHTML = "no streetview available"; 
    } 
    } 

    /* 
    * 'getBearing' 
    * calcs bearing from two latlngs 
    * 
    */ 
    GMap.prototype.getBearing = function (fromLatLng, targetLatLng) { 
    var DEGREE_PER_RADIAN = 57.2957795; 
    var RADIAN_PER_DEGREE = 0.017453; 

    var dlat = targetLatLng.lat - fromLatLng.lat; 
    var dlng = targetLatLng.lng - fromLatLng.lng; 
    // We multiply dlng with cos(endLat), since the two points are very closeby, 
    // so we assume their cos values are approximately equal. 
    var bearing = Math.atan2(dlng * Math.cos(fromLatLng.lat * RADIAN_PER_DEGREE), dlat) 
      * DEGREE_PER_RADIAN; 

    if (bearing >= 360) { 
     bearing -= 360; 
    } else if (bearing < 0) { 
     bearing += 360; 
    } 
    return bearing; 
    } 

    /* 
    * 'add_polygon' 
    * adds a polygon to a map using an array of lat lng coords 
    * these are pushed in the order they appear in the locationarray 
    * 
    * @param array locationarray - which event/change type triggers update of this element 
    * 
    */ 
    GMap.prototype.add_polygon = function (args) { 

//construct and store polygon 
    var polyobj = model.array_defaults(args, {name: "polygon", polygon: null, infohtml: null, box: null, focuson: false}); 
    //remove any same named polygon 
    if (this.polygons[args.name] != undefined) { 
     this.polygons[args.name].polygon.setMap(null); 
     this.polygons[args.name] = null; 
    } 


    var newpolygon = new Array(); 
    polyobj.box = new google.maps.LatLngBounds(); 
    for (var l in args.polygon) { 
     var point = new google.maps.LatLng(args.polygon[l].lat, args.polygon[l].lng); 
     newpolygon.push(point); 
     polyobj.box.extend(point); 
    } 
    polyobj.polygon = new google.maps.Polygon(
      { 
       map: this.map, 
       paths: newpolygon, 
       strokeColor: '#00ff00', 
       strokeOpacity: 0.75, 
       strokeWeight: 2, 
       fillColor: '#00ff00', 
       fillOpacity: 0.15 
      } 
    ); 
    this.polygons[args.name] = polyobj; 
    //set required changes to map 
    if (args.infohtml != null) { 
// content is forced into div with black font as google default is white text on white background ?!?!?! 
     polyobj.info = new google.maps.InfoWindow(
       { 
       content: "<div style='color:#000000'>" + args.infohtml + "</div>" 
       }); 
     var selfobj = this; 
     google.maps.event.addListener(this.polygons[args.name].polygon, 'click', function (event) { 
     var point = event.latLng; 
     selfobj.polygons[args.name].info.setPosition(point); 
     selfobj.polygons[args.name].info.open(selfobj.map); 
     }); 
    } 

    if (polyobj.focuson) { 
     this.map.fitBounds(polyobj.box); 
    } 
    } 


    /*****************************************************************/ 
    /* methods for CLIENT --> GMAP change */ 
    /*********************************************************S ********/ 

    /* 
    * allows gui to register elements so when changes/events occur in the map gui, its 
    * parent gui can be updated. 
    * @param string change_type - which event/change type triggers update of this element 
    * @param string change_return - data required to be returned eg latlng or address etc 
    * @param string callback - the page element identifier to update 
    */ 
    GMap.prototype.register_elem = function (change_type, event_return_cfg) { 
    switch (change_type) { 
     case "location": 
     switch (event_return_cfg.return_type) { 
      case "address": 
      this.gui_reg.location.address.push(event_return_cfg); 
      break; 
     } 
     break; 
    } 
    } 

    /*****************************************************************/ 
    /* methods for GMAP --> CLIENT change */ 
    /*****************************************************************/ 

    /* 
    * checks registered change type to send back to client 
    * @param string change_type - which event/change type triggers update of this element 
    * @param string data_request - data required to be returned 
    * @param string regelem - the parent gui identifier to update5 
    * @param object attr - which attribute to update eg for input, its value, for div its html 
    */ 
    GMap.prototype.update_client_go = function (change_type, data_request) { 
    switch (change_type) { 
     case "location": 
     var loc = this.get_viewport_coords(); 
     this.geo_query({type: "location", lat: loc.lat, lng: loc.lng}); 
    } 
    } 

    /* 
    * actions client_update 
    * @param string change_type - which event/change type triggers update of this element 
    * @param string data_request - data required to be returned 
    * @param string regelem - the parent gui identifier to update5 
    * @param object attr - which attribute to update eg for input, its value, for div its html 
    */ 
    GMap.prototype.update_client_do = function (pre_data, callback_data) { 
    if (callback_data.status != "ZERO_RESULTS") { 
     switch (pre_data.type) { 
     case "location": 
      var location_data_registrars = this.gui_reg.location; 
      for (var loc_type_list in location_data_registrars) { 
      switch (loc_type_list) { 
       case "address": 
       var address = callback_data.results[0].formatted_address; 
       for (var r in location_data_registrars[loc_type_list]) { 
        var event_return = location_data_registrars[loc_type_list][r]; 
        if (event_return != undefined) { 
        event_return.address = this.address_parse("postcode", address); 
        if (event_return.callback != undefined) { 
         eval(event_return.callback + "(event_return)"); 
        } 
        } 
       } 
       break; 
      } 
      } 
      break; 
     } 
    } 
    } 

    /*****************************************************************/ 
    /* PRIVATE METHODS */ 
    /*****************************************************************/ 
    GMap.prototype.address_parse = function (required_part, address) { 
    var result = ""; 
    address = address.split(", "); 
    var country = address[address.length - 1]; 
    switch (country) { 
     case "UK": 
     switch (required_part) { 
      case "postcode": 
      result = address[address.length - 2]; 
      result = result.substr(result.indexOf(" ") + 1); 
      break; 
     } 
     break; 
    } 
    return result; 
    } 

    GMap.prototype.loadedCallback = function (callback) { 
    this.calledbackonload = false; 
    google.maps.event.addListenerOnce(this.map, 'tilesloaded', function() { 
     google.maps.event.clearListeners(this.map, 'idle'); 
     eval(callback + '()'); 
    }); 
    google.maps.event.addListenerOnce(this.map, 'idle', function() { 
     eval(callback + '()'); //add idle as a catch all 
    }); 
    /* 
    google.maps.event.addListenerOnce(this.map, 'idle', function() { 
    eval(callback + '()') 
    }); 
    */ 
    } 

    /* 
    * zooms map to next level from current depending on dir being '+' or '-' 
    */ 
    GMap.prototype.incrementZoom = function (dir, callback) { 
    var newZoom = this.map.getZoom(); 
    if (dir == '+') { 
     newZoom++; 
    } 
    if (dir == '-') { 
     newZoom--; 
    } 
    this.map.setZoom(newZoom); 
    if (callback != undefined) { 
     this.loadedCallback(callback); 
    } 
    } 

    /* 
    * zooms map to fully zoomed in 
    */ 
    GMap.prototype.zoomMax = function (callback) { 
    this.map.setZoom(this.mapoptions.maxzoom); 
    if (callback != undefined) { 
     this.loadedCallback(callback); 
    } 
    } 

    /* 
    * zooms map to fully zoomed out 
    */ 
    GMap.prototype.zoomMin = function (callback) { 
    this.map.setZoom(this.mapoptions.minzoom); 
    if (callback != undefined) { 
     this.loadedCallback(callback); 
    } 
    } 

    /* 
    * zooms map to contain the given box as per gmaps southwest/northeast corner specs 
    */ 
    GMap.prototype.boxZoom = function (latfrom, latto, lngfrom, lngto) { 
    var bottomleft = {lat: latfrom, lng: lngfrom}; 
    var topright = {lat: latto, lng: lngto}; 
    var box = new google.maps.LatLngBounds(bottomleft, topright); 
    this.map.fitBounds(box); 
    } 

    /* 
    * forces zoom in to min max params and returns true if it has been constrained 
    * additional callback if required for when zoom to constraints has finished 
    */ 
    GMap.prototype.constrainzoom = function (callback) { 
    if (this.map.getZoom() > this.mapoptions.maxzoom) { 
     this.map.setZoom(this.mapoptions.maxzoom); 
    } else if (this.map.getZoom() < this.mapoptions.minzoom) { 
     this.map.setZoom(this.mapoptions.minzoom); 
    } else { 
     return false; 
    } 
    if (callback != undefined) { 
     this.loadedCallback(callback); 
    } 
    return true; 
    } 

    /*add extras to generic map object*/ 
    google.maps.Map.prototype.clearMarkers = function() { 
    for (var i = 0; i < this.markers.length; i++) { 
     this.markers[i].setMap(null); 
    } 
    this.markers = new Array(); 
    }; 
    /* 
    * places an existing div by id as a map control 
    */ 
    GMap.prototype.addcontrol = function (divid, posn) { 
    if (posn == undefined) { 
     posn = google.maps.ControlPosition.TOP_LEFT; 
    } 
    this.map.controls[posn].push(document.getElementById(divid)); 
    } 
    /* translate normal functions to internal map object */ 
    /* trigger setup */ 
    this.__construct(mapId, options); 
}