I am working on Google Maps and want to implement a feature where a user can draw a box/rectangle using his/her mouse to select a region on map (like selecting multiple files in windows). Upon selection, I want to get all the markers that fall in the region. I have been looking around both Google Maps api and search but I am unable to find a solution. I tried using jQuery Selectable for selection but all it returns is a bunch of divs from which I am unable to determine if any marker is selected or not.
I found a Library keydragzoom (http://google-maps-utility-library-v3.googlecode.com/svn/tags/keydragzoom/1.0/docs/reference.html) and used it to draw a rectangle on the page.
Later, I edit the library and stopped it from zooming the selected area and instead made it return the correct co-ordinates in 'dragend' event. Then I manually looped through all the marker on the map to find the markers that are within that particular region. The library was not giving me the proper co-ordinates to I made the following changes.
Changed the DragZoom function to
var prj = null;
function DragZoom(map, opt_zoomOpts) {
var ov = new google.maps.OverlayView();
var me = this;
ov.onAdd = function () {
me.init_(map, opt_zoomOpts);
};
ov.draw = function () {
};
ov.onRemove = function () {
};
ov.setMap(map);
this.prjov_ = ov;
google.maps.event.addListener(map, 'idle', function () {
prj = ov.getProjection();
});
}
and DragZoom.prototype.onMouseUp_ function to
DragZoom.prototype.onMouseUp_ = function (e) {
this.mouseDown_ = false;
if (this.dragging_) {
var left = Math.min(this.startPt_.x, this.endPt_.x);
var top = Math.min(this.startPt_.y, this.endPt_.y);
var width = Math.abs(this.startPt_.x - this.endPt_.x);
var height = Math.abs(this.startPt_.y - this.endPt_.y);
var points={
top: top,
left: left,
bottom: top + height,
right: left + width
};
var prj = this.prjov_.getProjection();
// 2009-05-29: since V3 does not have fromContainerPixel,
//needs find offset here
var containerPos = getElementPosition(this.map_.getDiv());
var mapPanePos = getElementPosition(this.prjov_.getPanes().mapPane);
left = left + (containerPos.left - mapPanePos.left);
top = top + (containerPos.top - mapPanePos.top);
var sw = prj.fromDivPixelToLatLng(new google.maps.Point(left, top + height));
var ne = prj.fromDivPixelToLatLng(new google.maps.Point(left + width, top));
var bnds = new google.maps.LatLngBounds(sw, ne);
//this.map_.fitBounds(bnds);
this.dragging_ = false;
this.boxDiv_.style.display = 'none';
/**
* This event is fired when the drag operation ends.
* Note that the event is not fired if the hot key is released before the drag operation ends.
* #name DragZoom#dragend
* #param {GLatLngBounds} newBounds
* #event
*/
google.maps.event.trigger(this, 'dragend', points);
}
};
Related
I am using TransformGestureEvent and StartDrag and StopDrag events and I am having some issues.
I will do my best to explain, When I zoom in, my image zooms in and its centered while zooming. After I zoom in, I start to drag to the top of my image, when I reach the top I cant scroll now more (everything is working as expected so far) but when I goto zoom out my image y axis is no longer at the top, there is a blank white space where my image should be.
Here is my code:
mapMC.addEventListener(TransformGestureEvent.GESTURE_ZOOM, zoom);
mapMC.addEventListener(MouseEvent.MOUSE_DOWN, dragStart);
mapMC.addEventListener(MouseEvent.MOUSE_UP, dragEnd);
//Zooming Method
function zoom (event:TransformGestureEvent):void{
var locX:Number=event.localX;
var locY:Number=event.localY;
var stX:Number=event.stageX;
var stY:Number=event.stageY;
var prevScaleX:Number=mapMC.scaleX;
var prevScaleY:Number=mapMC.scaleY;
var mat:Matrix;
var externalPoint=new Point(stX,stY);
var internalPoint=new Point(locX,locY);
mapMC.scaleX *= event.scaleX;
mapMC.scaleY *= event.scaleY;
if(mapMC.scaleX > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleY > 6){
mapMC.scaleX=prevScaleX;
mapMC.scaleY=prevScaleY;
}
if(mapMC.scaleX < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
if(mapMC.scaleY < 1){
mapMC.scaleX=1;
mapMC.scaleY=1;
}
mat=mapMC.transform.matrix.clone();
MatrixTransformer.matchInternalPointWithExternal(mat,internalPoint,externalPoint);
mapMC.transform.matrix=mat;
}
//Dragging Start Method
function dragStart(e:MouseEvent):void
{
mapMC.startDrag(false, new Rectangle(0,0,-mapMC.width + stage.stageWidth, -mapMC.height + stage.stageHeight));
}
//Dragging Stop Method
function dragEnd(e:MouseEvent):void
{
mapMC.stopDrag();
}
What I am expected to happen is to zoom in on centre, be able to scroll within the Rectangle in my startDrag and zoom out on center while the top of the image stays at the top of the stage and the left of the image stays on the left of the stage.
I have tried adding these two lines of code in my zoom method, it works but I cant zoom in on center:
mapMC.y = 0;
mapMC.x = 0;
Here is a link to a sample project that will show you what I mean
https://drive.google.com/open?id=0B-p_9V3gzZZTcXpQZzI0RU9ZY0k
Since the builtin touch gestures of Air are not very handy for this, I've implemented a selfmade zoom functionality using MultitouchInputMode.TOUCH_POINT.
import flash.events.Event;
import flash.geom.Rectangle;
import flash.events.MouseEvent;
import flash.ui.MultitouchInputMode;
import flash.events.TouchEvent;
import flash.geom.Point;
//Vars
var touchpoints:Array = []
var touch_mode:String = null
var touch_start:Point
var map_start:Point
var map_zoom:Number
var map_width:Number
var map_height:Number
var zoom_startdist:Number
//Config
var max_zoom:Number = 6
var min_zoom:Number = 1
var map_bounds:Rectangle = new Rectangle(0,0,mapMC.width,mapMC.height) // this defines the area in which the map should fit
//Allow Touch Gestures
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
//Zoom and Drag Event Listeners
stage.addEventListener(TouchEvent.TOUCH_BEGIN, touchBegin)
stage.addEventListener(TouchEvent.TOUCH_MOVE, touchMoved)
stage.addEventListener(TouchEvent.TOUCH_END, touchEnd)
// Touch Handlers
function touchBegin(e:TouchEvent){
if(touchpoints.length<2){ // only accept 2 active touchpoints, ignore the 3rd,4th,etc
touchpoints.push({id:e.touchPointID,x:e.stageX,y:e.stageY})
touchpointsChanged()
}
}
function touchMoved(e:TouchEvent){
var touchpoint:Object = getTouchPointById(e.touchPointID) // get current touchpoint...
if(touchpoint){
// ... and update the position
touchpoint.x = e.stageX
touchpoint.y = e.stageY
touchpointMoved()
}
}
function touchEnd(e:TouchEvent){
removeTouchPoint(e.touchPointID)
touchpointsChanged()
}
// Pan & Zoom logic
function touchpointsChanged(){
if(touchpoints.length==1){ // 1 touch point => panning
startPan()
}else if(touchpoints.length==2){ // 2 touch points => zooming
startZoom()
}
}
function startPan(){
touch_mode = 'pan'
touch_start = new Point(touchpoints[0].x,touchpoints[0].y)
map_start = new Point(mapMC.x,mapMC.y)
}
function startZoom(){
touch_mode = 'zoom'
touch_start = getZoomCenter()
zoom_startdist = getZoomDist()
map_start = new Point(mapMC.x,mapMC.y)
map_zoom = mapMC.scaleX
map_width = mapMC.width
map_height = mapMC.height
}
function touchpointMoved(){
switch(touch_mode){
case 'pan':
mapMC.x = map_start.x + touchpoints[0].x - touch_start.x
mapMC.y = map_start.y + touchpoints[0].y - touch_start.y
break
case 'zoom':
var current_scale:Number = map_zoom*getZoomFactor() // get current zoom factor (relative to the previous zoom of the map)
current_scale = Math.min(max_zoom,Math.max(min_zoom,current_scale)) // limit zoom (as defined in -> Config)
mapMC.scaleX = mapMC.scaleY = current_scale
// Set map position to the current center of zoom
var zoom_pos:Point = getZoomCenter()
mapMC.x = map_start.x + zoom_pos.x - touch_start.x
mapMC.y = map_start.y + zoom_pos.y - touch_start.y
// Correct map position regarding the scaling
mapMC.x += -(current_scale-map_zoom)*map_width*((touch_start.x-map_start.x)/map_width)/map_zoom
mapMC.y += -(current_scale-map_zoom)*map_height*((touch_start.y-map_start.y)/map_height)/map_zoom
break
}
// Make sure the map doesnt leave its defined area - see Config (map_bounds)
if(mapMC.x>map_bounds.x)
mapMC.x = map_bounds.x
else if(mapMC.x+mapMC.width<map_bounds.x+map_bounds.width)
mapMC.x = map_bounds.x+map_bounds.width-mapMC.width
if(mapMC.y>map_bounds.y)
mapMC.y = map_bounds.y
else if(mapMC.y+mapMC.height<map_bounds.y+map_bounds.height)
mapMC.y = map_bounds.y+map_bounds.height-mapMC.height
}
// Helper functions
function getTouchPointById(id:int):Object{
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id)
return touchpoints[i]
}
return null
}
function removeTouchPoint(id:int){
for(var i:uint=0;i<touchpoints.length;i++){
if(touchpoints[i].id==id){
touchpoints.splice(i,1)
return
}
}
}
function getZoomCenter():Point{
//get the average of the 2 touchpoints
return new Point((touchpoints[0].x+touchpoints[1].x)/2,(touchpoints[0].y+touchpoints[1].y)/2)
}
function getZoomDist():Number{
// calculate the distance between the 2 touchpoints
return getDist(touchpoints[0].x,touchpoints[0].y,touchpoints[1].x,touchpoints[1].y)
}
function getZoomFactor():Number{
// calculate the difference of distance between the 2 touchpoints from when the zoom gesture started
return getZoomDist()/zoom_startdist
}
function getDist(x1:Number,y1:Number,x2:Number,y2:Number){
// pythagoras, yo
var deltaX:Number = x2-x1
var deltaY:Number = y2-y1
return Math.sqrt(deltaX*deltaX + deltaY*deltaY)
}
Let me know if anything is unclear, I'll try to add more comments.
I'm using code found here: Integrating Spiderfier JS into markerClusterer V3 to explode multi-markers with exact same long / lat to restrict zoom levels when clicking on MarkerClusterer created clusters containing points at the same location.
Live example is here:
http://www.adultlearnersfestival.com/newsite/yourarea/map.html
I'm getting an error in Firebug however:
Error: TypeError: markers is undefined
and can't work out what's causing it. The specific code is:
var minClusterZoom = 14;
mc.setMaxZoom(minClusterZoom);
gm.event.addListener(mc, 'clusterclick', function(cluster) {
map.fitBounds(cluster.getBounds()); // Fit the bounds of the cluster clicked on
if( map.getZoom() > minClusterZoom+1 ) // If zoomed in past 15 (first level without clustering), zoom out to 15
map.setZoom(minClusterZoom+1);
});
Any help much appreciated.
- Tom
I took a different approach suggested here: markerClusterer on click zoom and edited the MarkerClusterer source as follows
from this
/**
* Triggers the clusterclick event and zoom's if the option is set.
*/
ClusterIcon.prototype.triggerClusterClick = function() {
var markerClusterer = this.cluster_.getMarkerClusterer();
// Trigger the clusterclick event.
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
if (markerClusterer.isZoomOnClick()) {
// Zoom into the cluster.
this.map_.fitBounds(this.cluster_.getBounds());
}
};
to this
/**
* Triggers the clusterclick event and zoom's if the option is set.
*/
ClusterIcon.prototype.triggerClusterClick = function() {
var markerClusterer = this.cluster_.getMarkerClusterer();
// Trigger the clusterclick event.
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
if (markerClusterer.isZoomOnClick()) {
// Zoom into the cluster.
this.map_.fitBounds(this.cluster_.getBounds());
// modified zoom in function
if( this.map_.getZoom() > markerClusterer.getMaxZoom()+1 )
this.map_.setZoom(markerClusterer.getMaxZoom()+1);
}
};
Looks like an error in the MarkerClusterer to me. Inside this function in the for loop, markers is undefined, which means this.getMarkers() is returning undefined, looks to me like it is just wrong:
/**
* Returns the bounds of the cluster.
*
* #return {google.maps.LatLngBounds} the cluster bounds.
*/
Cluster.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
var markers = this.getMarkers();
for (var i = 0, marker; marker = markers[i]; i++) {
bounds.extend(marker.getPosition());
}
return bounds;
};
probably should be something like (not tested):
/**
* Returns the bounds of the cluster.
*
* #return {google.maps.LatLngBounds} the cluster bounds.
*/
Cluster.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
var markers = this.getMarkers();
if (markers && markers.length)
{
for (var i = 0; i < markers.length; i++) {
bounds.extend(markers[i].getPosition());
}
}
return bounds;
};
Works using MarkerClustererPlus
I solved the issue changing this:
Cluster.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
var markers = this.getMarkers();
for (var i = 0, marker; marker = markers[i]; i++) {
bounds.extend(marker.getPosition());
}
return bounds;
};
to this:
Cluster.prototype.getBounds = function() {
var bounds = new google.maps.LatLngBounds(this.center_, this.center_);
var markers = this.getMarkers();
var minZoom =10
mc.setMaxZoom(minZoom);//The maximum zoom level that a marker can be part of a cluster
for (var i = 0; i < markers.length; i++) {
bounds.extend(marker.getPosition());//Extends this bounds to contain the given point.
}
if( map.getZoom() > minZoom+1 ){// If zoomed in past 11, the first level without clustering, zoom out to 11.
map.setZoom(minZoom+1);
}
return bounds;
};
In Google maps API v2, map of our country was nicely fitted to 700x400px map with the following:
map.getBoundsZoomLevel(<bounds of our country>)
But in API v3, the map.fitBounds() method doesn't fit it at that zoom level to 700x400 - it zooms out one level.
This means that map.fitBounds() counts with some "grace margin" or something.
How can I affect the size of this margin?
Here's a solution that will zoom into the map as far as possible without a custom margin. You should be able to adapt it to account for some margin if you want to.
My solution is based on this comment in a Google Groups thread. Unfortunately, the call to helper.getProjection() always returned undefined, so I adapted the above answer a bit and came up with this working code.
Just replace your existing calls to map.fitBounds(bounds) with myFitBounds(map, bounds):
function myFitBounds(myMap, bounds) {
myMap.fitBounds(bounds);
var overlayHelper = new google.maps.OverlayView();
overlayHelper.draw = function () {
if (!this.ready) {
var projection = this.getProjection(),
zoom = getExtraZoom(projection, bounds, myMap.getBounds());
if (zoom > 0) {
myMap.setZoom(myMap.getZoom() + zoom);
}
this.ready = true;
google.maps.event.trigger(this, 'ready');
}
};
overlayHelper.setMap(myMap);
}
// LatLngBounds b1, b2 -> zoom increment
function getExtraZoom(projection, expectedBounds, actualBounds) {
var expectedSize = getSizeInPixels(projection, expectedBounds),
actualSize = getSizeInPixels(projection, actualBounds);
if (Math.floor(expectedSize.x) == 0 || Math.floor(expectedSize.y) == 0) {
return 0;
}
var qx = actualSize.x / expectedSize.x;
var qy = actualSize.y / expectedSize.y;
var min = Math.min(qx, qy);
if (min < 1) {
return 0;
}
return Math.floor(Math.log(min) / Math.log(2) /* = log2(min) */);
}
// LatLngBounds bnds -> height and width as a Point
function getSizeInPixels(projection, bounds) {
var sw = projection.fromLatLngToContainerPixel(bounds.getSouthWest());
var ne = projection.fromLatLngToContainerPixel(bounds.getNorthEast());
return new google.maps.Point(Math.abs(sw.y - ne.y), Math.abs(sw.x - ne.x));
}
Now, the method fitBounds has a second parameter that represents the size of the padding. For those who want to remove it, you just need to pass 0.
Map.map.fitBounds(bounds, 0);
New method signature: fitBounds(bounds:LatLngBounds|LatLngBoundsLiteral, padding?:number)
I'm attempting to draw many circles (around 1000) on a google map, at various locations and sizes, and then binding a click event to them. But this many calls of new google.maps.Circle(parameters); makes the page loading slow, and sometimes it just hangs forever, so I'd like to figure out if there's a better/faster way to accomplish what I'm trying to do.
I see that there's something called a kml layer, but there doesn't appear to be any easy way to draw filled circles with it and I'm not sure if I can still bind click events to each individual circle in the layer or not.
Looking at the circle workaround on the google KML faq page, I'm not sure if generating a KML file that contains thousands of circles similar to this would end up saving any time.
I also have no idea how to go about generating this kml file.
Finally, take into consideration that I'm pulling the circles I'm attempting to draw from a database, so I'd either have to generate the KML file on the fly for use or generate a new file every time a circle is removed or added from the DB so that the file stays up to date.
Of course, if there's another alternative, I'm all ears!
With the help of others via the Google Maps API v3 Group, I was able to implement a map overlay that handles 10,000 points suprisingly well. The trick is to use a canvas tile overlay, which minimizes the number of DOM elements in exchange for much simpler/lighter-weight POJsOs (plain old JavaScript objects).
Demo page w/mouse click events (API v2 only): http://notebook.kulchenko.com/maps/datamark
Demo page w/cursor swapping (API v2 and v3): http://notebook.kulchenko.com/maps/gridmark
Here is yet another example that demonstrates how to render multiple objects on Google Map using Overlay approach. Since the performance could degrade considerably while the amount of objects (e.g. google.maps.Circle) is increasing, it is proposed to render objects using canvas element instead of divone.
Example
The example demonstrates how to render 1k objects (cities)
var overlay;
USCitiesOverlay.prototype = new google.maps.OverlayView();
function USCitiesOverlay(map) {
this._map = map;
this._cities = [];
this._radius = 6;
this._container = document.createElement("div");
this._container.id = "citieslayer";
this.setMap(map);
this.addCity = function (lat, lng,population) {
this._cities.push({position: new google.maps.LatLng(lat,lng),population: population});
};
}
USCitiesOverlay.prototype.createCityIcon = function (id,pos,population) {
var cityIcon = document.createElement('canvas');
cityIcon.id = 'cityicon_' + id;
//calculate radius based on poulation
this._radius = population / 100000;
cityIcon.width = cityIcon.height = this._radius * 2;
cityIcon.style.width = cityIcon.width + 'px';
cityIcon.style.height = cityIcon.height + 'px';
cityIcon.style.left = (pos.x - this._radius) + 'px';
cityIcon.style.top = (pos.y - this._radius) + 'px';
cityIcon.style.position = "absolute";
var centerX = cityIcon.width / 2;
var centerY = cityIcon.height / 2;
var ctx = cityIcon.getContext('2d');
ctx.fillStyle = 'rgba(160,16,0,0.6)';
ctx.beginPath();
ctx.arc(centerX, centerY, this._radius, 0, Math.PI * 2, true);
ctx.fill();
return cityIcon;
};
USCitiesOverlay.prototype.ensureCityIcon = function (id,pos,population) {
var cityIcon = document.getElementById("cityicon_" + id);
if(cityIcon){
cityIcon.style.left = (pos.x - this._radius) + 'px';
cityIcon.style.top = (pos.y - this._radius) + 'px';
return cityIcon;
}
return this.createCityIcon(id,pos,population);
};
USCitiesOverlay.prototype.onAdd = function () {
var panes = this.getPanes();
panes.overlayLayer.appendChild(this._container);
};
USCitiesOverlay.prototype.draw = function () {
var zoom = this._map.getZoom();
var overlayProjection = this.getProjection();
var container = this._container;
this._cities.forEach(function(city,idx){
var xy = overlayProjection.fromLatLngToDivPixel(city.position);
var cityIcon = overlay.ensureCityIcon(idx,xy,city.population);
container.appendChild(cityIcon);
});
};
USCitiesOverlay.prototype.onRemove = function () {
this._container.parentNode.removeChild(this._container);
this._container = null;
};
function getRandomInterval(min, max) {
return Math.random() * (max - min) + min;
}
function generateCityMap(count) {
var citymap = [];
var minPos = new google.maps.LatLng(49.25, -123.1);
var maxPos = new google.maps.LatLng(34.052234, -74.005973);
for(var i = 0; i < count;i++)
{
var lat = getRandomInterval(minPos.lat(),maxPos.lat());
var lng = getRandomInterval(minPos.lng(),maxPos.lng());
var population = getRandomInterval(100000,1000000);
citymap.push({
location: new google.maps.LatLng(lat, lng),
population: population
});
}
return citymap;
}
function initialize() {
var mapOptions = {
zoom: 4,
center: new google.maps.LatLng(37.09024, -95.712891),
mapTypeId: google.maps.MapTypeId.TERRAIN
};
var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
overlay = new USCitiesOverlay(map);
//overlay.addCity(40.714352, -74.005973); //chicago
//overlay.addCity(40.714352, -74.005973); //newyork
//overlay.addCity(34.052234, -118.243684); //losangeles
//overlay.addCity(49.25, -123.1); //vancouver
var citymap = generateCityMap(1000);
citymap.forEach(function(city){
overlay.addCity(city.location.lat(), city.location.lng(),city.population);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px;
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<div id="map-canvas"></div>
Forget about KML, custom tiles are the way to go.
Have a look at these county maps:
http://maps.forum.nu/v3/gm_customTiles.html (check the "Density" box).
and
http://maps.forum.nu/gm_main.html?lat=31.428663&lon=-110.830078&z=4&mType=10
(click on the map to get county info)
These maps have 3000+ polygons, (not circles), and they load fast. The first link is API V3, the second is API V2.
The second map (V2) has click events. The click event handler is attached to the map itself, and it sends an AJAX call to the server with the lat/lon of the click. The server side script then looks this lat/lon up in the database to determine which county was clicked.
I have the following code which lets the user plot two points on a Google MAP. I then want to be able to catch the event for each point(marker) being dragged to a new location. I am bad at Javascript and have spent hours trying to do this so I think it's time I get some help..
What I am trying to do is get the user to plot two points(markers) draggable on the map. I then want to be able to have my script write the positions(lat,long) to the document. I will then calculate the distance between these as part of a shipping app I am making.
I would like to have the contents of the document (lat,long) updated when a marker(point) is dragged to a new location.
Also, I fixed a schoolboy error where the point vars were being decalred inside the switch statement. My problem is fixed by moving the Add event listener statements inside the switch statement. Thanks Cannonade :)
The next thing now is to try and calculate the distance (crow flies) between the two points
Again, thanks for you help.. appreciated as always!!
Updated Code that works:
var map = null;
var geocoder = null;
var zoom = 15;
var first_point = false;
var boundary = new Array();
var cCount = 0;
var point1;
var point2;
function initialize() {
if (GBrowserIsCompatible()) {
first_point = false;
map = new GMap2(document.getElementById("map_canvas"));
var center = new GLatLng(37.4419, -122.1419);
map.setCenter(center, zoom);
GEvent.addListener(map, "click", function(overlay,point)
{
if (overlay != null)
{}
else
{
var n = boundary.length;
switch (cCount)
{
case 0:
point1 = new GMarker(point,{draggable: true});
map.addOverlay(point1);
cCount++;
GEvent.addListener(point1, "dragend", function()
{
alert('P1 Dragged');
});
break;
case 1:
point2 = new GMarker(point,{draggable: true});
map.addOverlay(point2);
cCount++;
GEvent.addListener(point2, "dragend", function()
{
alert('P2 Dragged');
});
break;
case 2:
map.clearOverlays();
cCount=0;
break;
}
}
});
map.addControl(new GSmallMapControl());
geocoder = new GClientGeocoder();
}
}
I have taken your code and made the following fixes:
Fixed the unbalanced brackets I mentioned in the comment.
Moved the two addListener calls into the switch statement so that the point1 and point2 variables are still in scope when you attach the events.
You can check out the example here (source).
Edit:
Here is some Javascript code to get the linear distance between two points (in meters):
/* Convert degress to radians */
function deg2rad(deg) {
return deg / (180 / Math.PI);
}
/* Calculate distance between two points */
function point_distance(a, b) {
var r = 6378700;
var lat1 = a.y;
var lat2 = b.y;
var lon1 = a.x;
var lon2 = b.x;
var dist = r * Math.acos(Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.cos(deg2rad(lon1 - lon2)));
return dist;
}
This is based on the approximate radius of the earth being 6378700m.