Skip to content

Instantly share code, notes, and snippets.

@kulesa
Created July 5, 2010 08:21
Show Gist options
  • Save kulesa/464135 to your computer and use it in GitHub Desktop.
Save kulesa/464135 to your computer and use it in GitHub Desktop.
# Helper function to get rid of repeating bindTo calls
google.maps.MVCObject::bindProperties: (object, options) ->
for key, value of options
this.bindTo key, object, value
# Add listener for few events at a time.
# For example marker.addListener 'dragged', 'distance_changed', updateForm
google.maps.MVCObject::addListener: (events..., __func) ->
for event in events
google.maps.event.addListener this, event, (listener) => __func.call(this)
# RadiusWidget is a circle and sizer marker
class RadiusWidget extends google.maps.MVCObject
constructor: ->
circle: new google.maps.Circle { strokeWeight: 2 }
this.set 'distance', 50
this.bindTo 'bounds', circle
circle.bindProperties this, {
center: 'center'
map: 'map'
radius: 'radius'
}
this.addSizer_()
# magic funciton called on this.set 'distance', N
distance_changed: ->
this.set 'radius', this.get('distance') * 1000
# Adds sizer marker. When the sizer is dragged, changes circle radius
addSizer_: ->
sizer: new google.maps.Marker {
draggable: true
title: 'Drag me!'
icon: 'images/resize.png'
}
sizer.bindProperties this, {
map: 'map'
position: 'sizer_position'
}
google.maps.event.addListener sizer, 'drag', (event) => this.setDistance()
# Calculates distance between the sizer and center of the cirle and updates circle radius
setDistance: ->
pos: this.get 'sizer_position'
center: this.get 'center'
distance: this.distanceBetweenPoints_ center, pos
this.set 'distance', distance
# Moves sizer marker when the cirle is moved
center_changed: ->
bounds: this.get 'bounds'
if bounds
lng: bounds.getNorthEast().lng()
position: new google.maps.LatLng this.get('center').lat(), lng
this.set 'sizer_position', position
# Calculates distance between two given points
distanceBetweenPoints_: (p1, p2) ->
return 0 unless p1 and p2
R: 6371
dLat: (p2.lat() - p1.lat()) * Math.PI / 180
dLon: (p2.lng() - p1.lng()) * Math.PI / 180
a: Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(p1.lat() * Math.PI / 180) * Math.cos(p2.lat() * Math.PI / 180) *
Math.sin(dLon / 2) * Math.sin(dLon / 2)
c: 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
d: R * c
# DistanceWidget is a marker with attached resizable circle.
# Use 'position', 'distance' and 'bounds' properties to get information about center, radius and bounds of the cirle.
class DistanceWidget extends google.maps.MVCObject
constructor: (map) ->
this.set 'map', map
this.set 'position', map.getCenter()
marker: new google.maps.Marker {draggable: true,title: 'Move me'}
marker.bindProperties this, {
map: 'map'
position: 'position'
}
radiusWidget: new RadiusWidget()
radiusWidget.bindProperties this, {
map: 'map'
center: 'position'
}
this.bindProperties radiusWidget, {
distance: 'distance',
bounds: 'bounds'
}
# Display changed center and radius of the circle
displayInfo: ->
info: document.getElementById('info')
info.innerHTML: 'Position: ' + this.get('position') + ', distance: ' + this.get('distance')
# Create map, add distance widget to the map
init: ->
mapDiv: document.getElementById('map-canvas')
latlang: new google.maps.LatLng(37.790234970864, -122.39031314844)
map_options: {
center: latlang,
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
mapTypeControl: false
}
map: new google.maps.Map mapDiv, map_options
distanceWidget: new DistanceWidget map
distanceWidget.addListener 'distance_changed', 'position_changed', displayInfo
google.maps.event.addDomListener window, 'load', init()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment