I have a requirement to draw a circle on google maps from a given static point. I tried to accomplish this by setting the circle setting center
as follows, center: new google.maps.LatLng(-34.397, 150.644)
after being drawn using the DrawingManager
.
But the issue here is the circle starts to draw from the mouse click location and once done the circle snaps into the given lat
and lng
as demo-ed in the fiddle : http://jsfiddle.net/hjkety80/1/
What I require is, regardless of where I click the circle should start drawing from the static point given. I apologize if the description is vague and would glad to clarify more if required. Any help / reference on this matter is greatly appreciated.
Thanks
EDIT
Even if the circle center binds to a marker is also a good workaround if possible
Click on the map and create a popup marker to select the point. From there, opt for the “Draw Radius.” Choose the proximity distance from the given address found within the radius options in the software. Once settings are entered, a map will show the highlighted parameters on the map.
Click anywhere on the map to create a circle. You may continue clicking outside the circles to create more circles. You can reposition (drag) the circles with your mouse by clicking+holding+moving.
I have created a working example for you. It's not using DrawingManager
because it's not suitable for what you want to achieve, instead I update the radius of the circle programatically.
So in this example, when map is loaded, user is presented with a pointer cursor and when he presses the mouse button, he will start drawing a circle with a center in your static_position
and the radius
of the new circle
is determined based on where he clicked.
The example includes geometry library (notice &libraries=geometry
when fetching the Google maps API) and leverages it's google.maps.geometry.spherical.computeDistanceBetween()
function to calculate distance in meters between your center and where user just clicked to get radius. If user doesn't immediately release the button and instead moves the mouse around, the circle will automatically adjust it's radius based on user movements with cursor. After the user releases the mouse, he can drag the map around and also circle stays editable for adjustments.
The example (Just press left mouse button on the map to start drawing. For better experience run in full page
mode):
var map = null;
function initialize(){
var static_position = new google.maps.LatLng(-34.397, 150.644);
var the_circle = null;
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: static_position,
zoom: 8,
draggable: false,
draggableCursor:'pointer'
});
var mousemove_handler;
google.maps.event.addListener(map, 'mouseup', function(e) {
if(mousemove_handler) google.maps.event.removeListener(mousemove_handler);
map.setOptions({draggable:true, draggableCursor:''}); //allow map dragging after the circle was already created
the_circle.setOptions({clickable:true});
});
google.maps.event.addListenerOnce(map, 'mousedown', function (mousedown_event) {
var radius = google.maps.geometry.spherical.computeDistanceBetween(static_position, mousedown_event.latLng); //get distance in meters between our static position and clicked position, which is the radius of the circle
the_circle = createCircle(static_position, radius); //create circle with center in our static position and our radius
mousemove_handler = google.maps.event.addListener(map, 'mousemove', function(mousemove_event) { //if after mousedown user starts dragging mouse, let's update the radius of the new circle
var new_radius = google.maps.geometry.spherical.computeDistanceBetween(static_position, mousemove_event.latLng);
console.log(new_radius);
the_circle.setOptions({radius:new_radius});
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
function createCircle(center, radius) {
var circle = new google.maps.Circle({
fillColor: '#ffffff',
fillOpacity: .6,
strokeWeight: 1,
strokeColor: '#ff0000',
draggable: false,
editable: true,
map: map,
center: center,
radius: radius,
clickable:false
});
google.maps.event.addListener(circle, 'radius_changed', function (event) {
console.log('circle radius changed');
});
google.maps.event.addListener(circle, 'center_changed', function (event) {
if(circle.getCenter().toString() !== center.toString()) circle.setCenter(center);
});
return circle;
}
<script src="//maps.google.com/maps/api/js?sensor=false&libraries=geometry&dummy=.js"></script>
<body style="margin:0px; padding:0px;">
<div id="map-canvas" style="height:400px; width:500px;"></div>
</body>
One option (from my answer to this question: How to style editable circle controls in Google Maps). DistanceWidget with a fixed center marker.
related questions:
code snippet:
function init() {
var mapDiv = document.getElementById('map-canvas');
var map = new google.maps.Map(mapDiv, {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var distanceWidget = new DistanceWidget(map);
google.maps.event.addListener(distanceWidget, 'distance_changed', function() {
displayInfo(distanceWidget);
});
google.maps.event.addListener(distanceWidget, 'position_changed', function() {
displayInfo(distanceWidget);
});
}
google.maps.event.addDomListener(window, 'load', init);
/**
* A distance widget that will display a circle that can be resized and will
* provide the radius in km.
*
* @param {google.maps.Map} map The map on which to attach the distance widget.
*
* @constructor
*/
function DistanceWidget(map) {
this.set('map', map);
this.set('position', map.getCenter());
var marker = new google.maps.Marker({
draggable: false,
icon: {
url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
size: new google.maps.Size(7, 7),
anchor: new google.maps.Point(4, 4)
},
title: 'Move me!'
});
// Bind the marker map property to the DistanceWidget map property
marker.bindTo('map', this);
// Bind the marker position property to the DistanceWidget position
// property
marker.bindTo('position', this);
// Create a new radius widget
var radiusWidget = new RadiusWidget();
// Bind the radiusWidget map to the DistanceWidget map
radiusWidget.bindTo('map', this);
// Bind the radiusWidget center to the DistanceWidget position
radiusWidget.bindTo('center', this, 'position');
// Bind to the radiusWidgets' distance property
this.bindTo('distance', radiusWidget);
// Bind to the radiusWidgets' bounds property
this.bindTo('bounds', radiusWidget);
}
DistanceWidget.prototype = new google.maps.MVCObject();
/**
* A radius widget that add a circle to a map and centers on a marker.
*
* @constructor
*/
function RadiusWidget() {
var circle = new google.maps.Circle({
strokeWeight: 2
});
// Set the distance property value, default to 50km.
this.set('distance', 50);
// Bind the RadiusWidget bounds property to the circle bounds property.
this.bindTo('bounds', circle);
// Bind the circle center to the RadiusWidget center property
circle.bindTo('center', this);
// Bind the circle map to the RadiusWidget map
circle.bindTo('map', this);
// Bind the circle radius property to the RadiusWidget radius property
circle.bindTo('radius', this);
this.addSizer_();
}
RadiusWidget.prototype = new google.maps.MVCObject();
/**
* Update the radius when the distance has changed.
*/
RadiusWidget.prototype.distance_changed = function() {
this.set('radius', this.get('distance') * 1000);
};
/**
* Add the sizer marker to the map.
*
* @private
*/
RadiusWidget.prototype.addSizer_ = function() {
var sizer = new google.maps.Marker({
draggable: true,
icon: {
url: "https://maps.gstatic.com/intl/en_us/mapfiles/markers2/measle_blue.png",
size: new google.maps.Size(7, 7),
anchor: new google.maps.Point(4, 4)
},
title: 'Drag me!'
});
sizer.bindTo('map', this);
sizer.bindTo('position', this, 'sizer_position');
var me = this;
google.maps.event.addListener(sizer, 'drag', function() {
// Set the circle distance (radius)
me.setDistance();
});
};
/**
* Update the center of the circle and position the sizer back on the line.
*
* Position is bound to the DistanceWidget so this is expected to change when
* the position of the distance widget is changed.
*/
RadiusWidget.prototype.center_changed = function() {
var bounds = this.get('bounds');
// Bounds might not always be set so check that it exists first.
if (bounds) {
var lng = bounds.getNorthEast().lng();
// Put the sizer at center, right on the circle.
var position = new google.maps.LatLng(this.get('center').lat(), lng);
this.set('sizer_position', position);
}
};
/**
* Calculates the distance between two latlng locations in km.
* @see http://www.movable-type.co.uk/scripts/latlong.html
*
* @param {google.maps.LatLng} p1 The first lat lng point.
* @param {google.maps.LatLng} p2 The second lat lng point.
* @return {number} The distance between the two points in km.
* @private
*/
RadiusWidget.prototype.distanceBetweenPoints_ = function(p1, p2) {
if (!p1 || !p2) {
return 0;
}
var R = 6371; // Radius of the Earth in km
var dLat = (p2.lat() - p1.lat()) * Math.PI / 180;
var dLon = (p2.lng() - p1.lng()) * Math.PI / 180;
var 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);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = R * c;
return d;
};
/**
* Set the distance of the circle based on the position of the sizer.
*/
RadiusWidget.prototype.setDistance = function() {
// As the sizer is being dragged, its position changes. Because the
// RadiusWidget's sizer_position is bound to the sizer's position, it will
// change as well.
var pos = this.get('sizer_position');
var center = this.get('center');
var distance = this.distanceBetweenPoints_(center, pos);
// Set the distance property for any objects that are bound to it
this.set('distance', distance);
};
function displayInfo(widget) {
var info = document.getElementById('info');
info.innerHTML = 'Position: ' + widget.get('position').toUrlValue(3) + ', distance: ' + widget.get('distance').toFixed(3);
}
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=geometry&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="info"></div>
<div id="map-canvas"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With