The User is allowed to draw a circle on the map, and then you can add markers - if the Marker is outside of the circle, then the circle should be enlarged to take the marker inside.
I could not find anything in the documentation:
Is there a possibility like: UserCircle.extend(event.overlay.location);
While event overlay is the marker.
I also tried to make this function on my own - but I get stuck on the radius.
Which unit is it? How can I convert it into degrees?
Any Ideas?
Thats what i made now...
function extendRegion(marker, drawing){
marker_lat = marker.getPosition().lat();
marker_lng = marker.getPosition().lng();
if(drawing.type == google.maps.drawing.OverlayType.CIRCLE){
var path = [marker.getPosition(), drawing.overlay.getCenter()];
var length = google.maps.geometry.spherical.computeDistanceBetween(path[0], path[1]);
if(length>drawing.overlay.getRadius()){
consloe.log('The Marker was outside the drawing, it is extended now.');
drawing.overlay.setRadius(length);
}
}
else if(drawing.type == google.maps.drawing.OverlayType.RECTANGLE){
ne_lat = drawing.overlay.getBounds().getNorthEast().lat();
ne_lng = drawing.overlay.getBounds().getNorthEast().lng();
sw_lat = drawing.overlay.getBounds().getSouthWest().lat();
sw_lng = drawing.overlay.getBounds().getSouthWest().lng();
var error=0;
if(marker_lat<sw_lat){
sw_lat = marker_lat;
error=1;
}
if(marker_lat>ne_lat){
ne_lat = marker_lat;
error=1;
}
if(marker_lng<sw_lng){
sw_lng = marker_lng;
error=1;
}
if(marker_lng>ne_lng){
ne_lng = marker_lng;
error=1;
}
if(error) {
console.log('The Marker was outside the drawing, it is extended now.');
drawing.overlay.setBounds({north: ne_lat, south: sw_lat, east: ne_lng, west: sw_lng});
}
}
}
Related
I want leaflet to work offline, without title, to show only a grid as titles. To have all the features of Leaflet, add plugins to draw a line, pin a marker, draw a polygon, zoom in / zoom out on shapes etc.
Is there a simple way to show just a simple grid?
Here's a custom GridLayer (that's already been implemented by the Leaflet authors). All you have to do is copy L.GridLayer.DebugCoords where you would normally load a tile layer.
var map = L.map('map', {
center: [0, 0],
zoom: 0
});
L.GridLayer.DebugCoords = L.GridLayer.extend({
createTile: function (coords, done) {
var tile = document.createElement('div');
//this adds tile coordinates; you may or may not want this
tile.innerHTML = [coords.x, coords.y, coords.z].join(', ');
tile.style.outline = '1px solid red';
/* // you don't need this artificial timeout for your application
setTimeout(function () {
done(null, tile); // Syntax is 'done(error, tile)'
}, 500 + Math.random() * 1500);
*/
return tile;
}
});
L.gridLayer.debugCoords = function(opts) {
return new L.GridLayer.DebugCoords(opts);
};
map.addLayer( L.gridLayer.debugCoords() );
Stand-alone, working example: http://leafletjs.com/examples/extending/gridcoords.html
Code taken from: http://leafletjs.com/examples/extending/extending-2-layers.html
I am relative new to Angularjs and i am currently working on a project but I hit an obstacle. I've been trying multiple ways to do this but Im all out of idea. Here is a picture of what I want to do:
Map
So on this picture, there are icons and what I want to do is upon clicking an icon, a pop-up window will appear. If you look at the shaded area on top right, that is how I want my the window to be and look like as I already built a template for it and right now the template is static div being displayed.
Here is my code so far:
$scope.cameraData = [];
$scope.markers = [];
$http.get($scope.docRoot + 'public/data/streetcams.json')
.success(function(data) {
$scope.cameraData = data;
for(var marker in $scope.cameraData) {
if($scope.cameraData.hasOwnProperty(marker)) {
$scope.cameraData[marker].icon = cameraIcon;
$scope.cameraData[marker].layer = 'video';
}
}
$scope.markers = $scope.cameraData;
}).error(function(data) {
console.log("Unable to load streecam data file");
});
$scope.windowOption = {
show:false
};
var x, y;
$scope.$on("leafletDirectiveMarker.map.click", function(event, args) {
console.log("this is where the marker is");
console.log (args.latlng.lat, args.latlng.lng);
for ( var marker in $scope.markers) {
x = args.latlng.lat;
y = args.latlng.lng;
if (marker.lat === x && marker.lng === y ) {
$scope.windowOption.show = !$scope.windowOption.show;
}
}*/
});
$scope.closePopupOnClick = function () {
$scope.windowOption.show = false;
};
So $scope.markers contains the information of all icons (title, lat and longitude) and my idea is to retrieve the latitude and longitude of each click event and compare that with latitude and longitude of each marker in the markers array, if they are equal then show to popup window. But it's not working and Im not sure what else to do. Any tips will help!
Thanks!
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
How do I draw a google.maps.Rectangle on a google map while holding the shift key and then once its drawn do something with its boundaries (like return all markers that fall within it)?
So I had the need to draw a simple rectangle on a google map and return an array of markers that fall within the rectangle. Surprisingly I couldn't find a simple example of this on the web. So I am posting this to help others with the same issue.
If you can see any glaring issues, please let me know although it seems to work for my needs at the moment.
The code assumes you have jQuery and have already stored your google map object in a variable called themap.
var shiftdown = false;
var gribBoundingBox = null;
var boxcomplete = false;
var original_click_pos = null;
$(window).keydown(function (evt) {
if (evt.which === 16) { // shift
shiftdown = true;
}
}).keyup(function (evt) {
if (evt.which === 16) { // shift
shiftdown = false;
}
});
function cleargribBoundingBox(){
if(gribBoundingBox !== null){
gribBoundingBox.setMap(null); // remove the rectangle
}
boxcomplete = false;
original_click_pos = null;
}
google.maps.event.addListener(themap, 'mousedown', function (e) {
if (shiftdown) {
themap.setOptions({
draggable: false
});
cleargribBoundingBox();
original_click_pos = e.latLng;
gribBoundingBox = new google.maps.Rectangle({
map: themap,
bounds: new google.maps.LatLngBounds(original_click_pos,original_click_pos),
fillOpacity: 0.15,
strokeWeight: 0.9,
clickable: false
});
}
});
google.maps.event.addListener(themap, 'mousemove', function (e) {
if(gribBoundingBox !== null){
if(!boxcomplete){
//moving mouse accross map, box is in process of being drawn
//lets update its bounds
var newbounds = new google.maps.LatLngBounds(original_click_pos,original_click_pos);
newbounds.extend(e.latLng);
gribBoundingBox.setBounds(newbounds);
} else{
//moving mouse accross map, box is present
}
} else {
//moving mouse over map, no bounding box present
//either no bounding box has been made yet or we are not holding shift and we are just dragging the map around
}
});
google.maps.event.addListener(themap, 'mouseup', function (e) {
if(gribBoundingBox !== null){ //we just completed a box
if(!boxcomplete){ //we just completed a box
boxcomplete = true;
themap.setOptions({
draggable: true
});
//check if markers are in the box
/*var boundsSelectionArea = new google.maps.LatLngBounds(
gribBoundingBox.getBounds().getSouthWest(),
gribBoundingBox.getBounds().getNorthEast()
);*/
}
}
});
https://jsfiddle.net/x1xpmhvk/
I am using the Geolocation Marker Script from the Google Maps Utilities Library V3 in order to display the position of a user.
What I want to achieve (I am a newbie to the Google Maps API!) is:
have the users current coordinates displayed (e.g. in a simple CSS container somewhere on the page)
connect an event to a marker. I should be triggered when the user is close.
Appreciate your help!
To display coordinates to the user, you would need a reference to a DOM Element. Then it's a simple matter of updating the content.
HTML On the Page
<div id="UserCoordinates">Waiting on GPS Position ...</div>
In Script
google.maps.event.addListener(GeoMarker, 'position_changed', function() {
var UserPosition = this.getPosition();
var DisplayElement = document.getElementById('UserCoordinates');
if(UserPosition === null) {
DisplayElement.innerHTML = 'Waiting on GPS Position...';
} else {
DisplayElement.innerHTML =
'Current Position: ' + UserPosition.toUrlValue();
}
});
This will show the user their current position as it changes. If you are going to continue using a full screen map, you'll probably want to implement the UserCoordinates div as a map control. The API Reference has a good overview and multiple examples on this.
Display an info window when the user is within X meters of a location
This is a little tricky because there are multiple scenarios to handle and you don't want the infowindow opening repeatedly as they move within your radius.
Distance calculation
I see you have a distance function in your code, but I recommend using the one in the Spherical Geometry library of the API. You just have to specifically load the library with your api script tag:
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?libraries=geometry&sensor=true_or_false">
</script>
Then you need to add to the position_changed event handler:
var IsWithinRadius = false; //assume they start outside of the circle
var RadiusInMeters = 1000; //within 1 km
var LocationOfInterest = map.getCenter();
google.maps.event.addListener(GeoMarker, 'position_changed', function() {
var UserPosition = this.getPosition();
var DisplayElement = document.getElementById('UserCoordinates');
if(UserPosition === null) {
DisplayElement.innerHTML = 'Waiting on GPS Position...';
IsWithinRadius = false; //you don't know where they are
} else {
DisplayElement.innerHTML =
'Current Position: ' + UserPosition.toUrlValue();
var IsCurrentPositionInRadius =
Math.abs(google.maps.geometry.spherical.computeDistanceBetween(
UserPosition, LocationOfInterest)) <= RadiusInMeters;
var JustEnteredRadius = !IsWithinRadius && IsCurrentPositionInRadius;
IsWithinRadius = IsCurrentPositionInRadius;
if(JustEnteredRadius) {
//trigger action here.
alert("Within raidus");
}
}
});
When I break on the first line in the call back function and do this
this.active --> true
this.deactivate() --> true
this.activate() --> true
this.deactivate() --> false
HOW CAN THIS HAPPEN?
Let me explain where this occurs.
This map has two layers and each layer has an EditingToolbar associated with it.
When the user pressed polygon draw (in the EditingToolbar), its being draw on the "polygon_layer".
When the user presses line draw or point draw the layer is switched and the user now draws on the "vectors" layer.
When I switch layers, I need to activate the correct button in the EditingToolbar, example:
The user draws polygons in the "polygon_layer" and now he want to draw lines. He presses draw lines button (in the EditingToolbar associated with the polygon_layer).
I switch layers and activate draw lines button on the EditingToolbar for that layer.
After a while, the user now wants to draw polygons again, so i deactivate all buttons in this layer, switch layers and activate the draw polygon button in the
EditingToolbar for the polygon_layer. and so on.
Now when I do this enough times (3 switches) I notice that the buttons don't get deactivate anymore.
So I tried to debug and got this totally unexpected error described above ( at the very top).
Please tell me what am I doing wrong.
I've appended my code and I'll put ERROR HERE where this occurs. This code is ready to run.
You can use the HTML code below, just change the reference to the JavaScript file that I've provided ( I've provided the contents of the JavaScript file)
JS FILE:
var map;
var editing_toolbar_polygon=null;
var editing_toolbar_vector=null;
var drag_control=null;
var vectors;
var polygon_layer=null;
var epsg900913 = new OpenLayers.Projection('EPSG:900913');
var epsg4326 = new OpenLayers.Projection('EPSG:4326');
//var epsg900913 = new OpenLayers.Projection('EPSG:900913');
// var epsg4326 = new OpenLayers.Projection('EPSG:4326');
var line_control;
var polygon_control;
var renderer;
function initialize() {
line_control, renderer=OpenLayers.Util.getParameters(window.location.href).renderer;
renderer= (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
// Create the map object
map = new OpenLayers.Map('map');
//Create a Google layer
var gmap = new OpenLayers.Layer.Google(
"Google Streets", // the default
{
numZoomLevels: 20,
projection: new OpenLayers.Projection("EPSG:900913")
}
);
var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic',
projection: new OpenLayers.Projection("EPSG:4326")});
var mystyle=new OpenLayers.StyleMap({
"default": new OpenLayers.Style({
fillColor: "#66ccff",
strokeColor: "#3399ff",
graphicZIndex: 2,
strokeWidth: 5,
}),
"temporary": new OpenLayers.Style({
fillColor:"#3399ff",
strokeColor: "#3399ff",
strokeWidth:5,
pointRadius:10
})
});
polygon_layer=new OpenLayers.Layer.Vector(
"Polygon Layer",
{
//renderers:renderer,
}
);
vectors= new OpenLayers.Layer.Vector(
"Vector Layer",
{
//renderers:renderer,
}
);
editing_toolbar_polygon=new OpenLayers.Control.EditingToolbar(polygon_layer);
editing_toolbar_vector=new OpenLayers.Control.EditingToolbar(vectors);
map.addLayers([gmap,wms,vectors,polygon_layer]);
map.addControl(new OpenLayers.Control.LayerSwitcher());
//map.addControl(new OpenLayers.Control.MousePosition());
map.addControl(editing_toolbar_polygon);
map.addControl(editing_toolbar_vector);
editing_toolbar_vector.deactivate();
//for the drag control to work you need to activate it
drag_control=new OpenLayers.Control.DragFeature(vectors);
map.addControl(drag_control);
find_control(editing_toolbar_polygon.getControlsByClass(new RegExp(".*DrawFeature")),"Point").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_vector.controls,e.object);
change_layer(polygon_layer,vectors);
change_control(editing_toolbar_polygon,editing_toolbar_vector);
picked_button.activate();
});
find_control(editing_toolbar_polygon.getControlsByClass(new RegExp(".*DrawFeature")),"Path").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_vector.controls,e.object);
change_layer(polygon_layer,vectors);
change_control(editing_toolbar_polygon,editing_toolbar_vector);
picked_button.activate();
});
find_control(editing_toolbar_vector.getControlsByClass(new RegExp(".*DrawFeature")),"Polygon").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_polygon.controls,e.object);
change_layer(vectors,polygon_layer);
change_control(editing_toolbar_vector,editing_toolbar_polygon);
picked_button.activate();
});
polygon_layer.events.register("beforefeatureadded",null,function(e){
polygon_layer.removeAllFeatures();
});
// line_control=new OpenLayers.Control.DrawFeature(vectors,OpenLayers.Handler.Path);
//polygon_control=new OpenLayers.Control.DrawFeature(vectors,OpenLayers.Handler.RegularPolygon);
//map.addControl(line_control);
//line_control.activate();
//map.addControl(polygon_control);
//polygon_control.activate();
// Zoom to Vancouver, BC
map.setCenter(new OpenLayers.LonLat(-123.12, 49.28).transform(epsg4326, epsg900913), 13);
}
function change_layer(current_layer,next_layer){
current_layer.setVisibility(false);
next_layer.setVisibility(true);
}
function change_control(current_control,next_control){
current_control.deactivate();
map.addControl(next_control);
}
//use this when you want to find a specific control type:
// DrawFeature cntrol has many types, Line, Polygon, Point.
// So what you do is pass an array of DrawFeature controls and a type(string), lets say "Point",
// then this function will return a DrawFeature thats specifically for drawing points
function find_control(controls,type){
var control;
for(var x in controls){
if(controls[x].displayClass.search(new RegExp(type+"$"))>0){
return controls[x];
}
}
return -1;
}
I just tried with a simple test.
When you desactivate a controller, you just remove the events of the controller.
So for OpenLayers.Control.LayerSwitcher, desactivate this controller is useless because nothing change and you can still choose a layer.
I think the best way is to remove the controller for your polygon and to add that for the lines.
When you select the "polygon_layer" :
map.addControl(editing_toolbar_polygon);
map.removeControl(editing_toolbar_vector);
When you select the "vectors" :
map.addControl(editing_toolbar_vector);
map.removeControl(editing_toolbar_polygon);