angular-leaflet-directive add rectangle around marker - javascript

I have leaflet map with a marker. On the side I have a form where I can specify the extent (in metres) of the square box that I would like to show on the map upon submitting the form.
I tried to replicate the example reported here http://leafletjs.com/reference.html#rectangle in angular but it does not work.
// define rectangle geographical bounds
var extent = 100; // metres
var bounds = [
[markerLat-extent/2, markerLon-extent/2],
[markerLat+extent/2, markerLon+extent/2]
];
var map = leafletData.getMap('mymap');
// create an orange rectangle
L.rectangle(bounds, {color: "#ff7800", weight: 1}).addTo(map);
I believe I am making a number of mistakes.
First of all, the lat/lon in the bounds should not mix with the extent expressed in metres.
Secondly, I get a "t.addLayer is not a function" error.
This is what I do in the Angular controller to get the map up and running:
angular.extend($scope, {
center : {
lat: latitudeUK,
lng: longitudeUK,
zoom: 5
},
defaults: {
scrollWheelZoom: false
},
tiles: {
url: "http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
options: {
attribution: '© OpenStreetMap contributors'
}
},
markers: {
pin: {
lat: startMarkerLatitude,
lng: startMarkerLongitude,
message: "Drag me to change center of the rectangle",
focus: true,
draggable: true
}
}
}
);
$scope.controls = {
scale: {
position: 'topleft',
metric: true
}
};
In the html page I have this simple call:
<leaflet id="mymap" center="center" controls="controls" tiles="tiles" markers="markers"></leaflet>
What am I missing? Thank you for your suggestions!
-- UPDATE --
I managed to add shapes to the map. In the case of a circle I can do the following:
leafletData.getMap('mymap').then(function(map) {
// Circle
var circleLocation = new L.LatLng(markerLat, markerLon);
var circleOptions = {
color: 'blue'
};
var shape = new L.Circle(circleLocation, extent, circleOptions);
map.addLayer(newShape);
});
What I cannot still do is to add a rectangle given its centre and the length of the sides correctly. It looks like the problem is when computing the bounding box of the rectangle.
I posted the question as a stand-alone one here, so it might be useful to check that question too.

Related

Leaflet : Draw circle always visible and centered even after a move or zoom

I'm trying to draw a circle on my Leaflet Map that should be always visible and centered even when user move or zoom in the map.
The following code works well when user move the map, but when the user zoom in or zoom out, the size of the circle is not updated. I would like to keep always the same dimension for the circle.
HTML
<div id="map" class="map" style="height:75vh;"></div>
JS
// Init Leaflet Map basically
this.map = L.map("map").setView([38.63, -90.23], 12);
window.map = this.map;
this.tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 20,
maxNativeZoom: 18,
attribution: '© OpenStreetMap, © CARTO'
});
this.tileLayer.addTo(this.map);
// Create circle that will be always visible and will have alwaus the same width.
this.circle = L.circle([38.63, -90.23], 3000, {
color: '#5d78ff',
fillOpacity: 0
}).addTo(this.map);
// Set circle always centered when map is moved.
this.map.on("moveend", (s) => {
this.circle.setLatLng(this.map.getCenter());
});
// todo: Set circle always centered when map is zoom in/out
this.map.on("zoomend", (s) => {
this.circle.setLatLng(this.map.getCenter());
console.log('test');
});
JSFIDDLE
https://jsfiddle.net/4uorasdn/
You can use CircleMarker instead of using Circle.
The relevant part of your code that needs to be changed should look something like this.
this.circle = L.circleMarker([38.63, -90.23], {
radius: 200,
color: '#5d78ff',
fillColor: '#f03',
fillOpacity: 0.2,
opacity: 1,
title: "test"
}).addTo(this.map);
And you can find a working jsfiddle here.

How can I prevent Google maps from being dragged out of the upper and lower boundaries? [duplicate]

Using google maps v3 javascript API i cannot find a way to block the panning of the map over the north pole or under the south pole.
As an example embedded maps on this page:
https://developers.google.com/maps/documentation/embed/guide
has the same behaviour, zooming out with the world view and panning north bring the view in a complete gray area.
How to prevent like it's done on official site http://maps.google.it ?
UPDATE - The following answer doesn't look to work anymore, I suppose it's because google maps API has been upgrade. I leave the code here for reference.
Thanks to geocodezip comments i modified Mike Williams' solution for my case.
Here is the fiddle example
Relevant code part:
google.maps.event.addListener(map, 'center_changed', function() {
checkBounds(map);
});
// If the map position is out of range, move it back
function checkBounds(map) {
var latNorth = map.getBounds().getNorthEast().lat();
var latSouth = map.getBounds().getSouthWest().lat();
var newLat;
if(latNorth<85 && latSouth>-85) /* in both side -> it's ok */
return;
else {
if(latNorth>85 && latSouth<-85) /* out both side -> it's ok */
return;
else {
if(latNorth>85)
newLat = map.getCenter().lat() - (latNorth-85); /* too north, centering */
if(latSouth<-85)
newLat = map.getCenter().lat() - (latSouth+85); /* too south, centering */
}
}
if(newLat) {
var newCenter= new google.maps.LatLng( newLat ,map.getCenter().lng() );
map.setCenter(newCenter);
}
}
Working for me with the attribute "restriction":
new google.maps.Map(document.getElementById('#mapCanvas'), {
zoom: 2,
center: {lat: 0, lng: 0},
tilt: 0,
restriction: {
latLngBounds: {north: 85, south: -85, west: -180, east: 180},
strictBounds: true
},
});

let user draw only one circle as source but some circles for destination

I have a very simple application (only one page) on which user draw polygons on the map and it also get lat, long, centre and radius of the circle that user drew.
I would like to limit user to draw only one circle as a source (Which I did and works fine), and then let him/her to select one or more destinations on the map. So, the first circle could be "source" and the next circles are "destinations"..
My question: how can I assign different variables to these circles in order to differentiate source place from destinations?
Here is my code (I used google api, Drawing library: https://developers.google.com/maps/documentation/javascript/examples/drawing-tools):
<script type="text/javascript">
(function () {
var circle;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-34.397, 150.644),
zoom: 8
};
var map = new google.maps.Map(document.getElementById('map-canvas'),
mapOptions);
var drawingManager = new google.maps.drawing.DrawingManager({
drawingMode: google.maps.drawing.OverlayType.MARKER,
drawingControl: true,
drawingControlOptions: {
position: google.maps.ControlPosition.TOP_CENTER,
drawingModes: [
google.maps.drawing.OverlayType.MARKER,
google.maps.drawing.OverlayType.CIRCLE,
google.maps.drawing.OverlayType.POLYGON,
google.maps.drawing.OverlayType.POLYLINE,
google.maps.drawing.OverlayType.RECTANGLE
]
},
markerOptions: {
icon: 'images/beachflag.png'
},
circleOptions: {
fillColor: '#ffff00',
fillOpacity: 1,
strokeWeight: 5,
clickable: false,
editable: true,
zIndex: 1
}
});
drawingManager.setMap(map);
google.maps.event.addListener(drawingManager, 'circlecomplete', onCircleComplete);
}
function onCircleComplete(shape) {
if (shape == null || (!(shape instanceof google.maps.Circle))) return;
if (circle != null) {
circle.setMap(null);
circle = null;
}
circle = shape;
var radius = circle.getRadius();
center = circle.getCenter();
var latitude = circle.getCenter().lat();
var longitude = circle.getCenter().lng();
}
google.maps.event.addDomListener(window, 'load', initialize);
})();
</script>
A simple approach:
Store all the circles, e.g. in an array, based on the length of the array you'll know if it's the first circle(source) or not(destination).
Setting different properties also isn't complicated, a google.maps.Circle is a MVCObject(and also a native JS-object), you may store custom properties e.g. via:
//vanilla javascript
shape.customProperty='customValue';
//MVCObject-specific, single property
shape.set('customProperty','customValue');
//MVCObject-specific, multiple properties
shape.setValues({customProperty :'customValue',
anotherProperty:'anotherValue'});
//shape-specific, multiple properties
shape.setOptions({customProperty :'customValue',
anotherProperty:'anotherValue'});
( Be sure that your custom property-names not compete with built-in names, e.g. center, radius etc.)
Possible implementation(stores a custom type-property for the circles, set to either source or destination):
function onCircleComplete(shape) {
var map=shape.getMap();
//create an array where we store the circles
if(!map.get('circles')){
map.set('circles',[]);
}
shape.setOptions(
(!map.get('circles').length)
?//first circle
{type:'source',
//a different fill when you want to
fillColor:'#ff0000'
}
://other circles
{type:'destination'}
);
//push the circles onto the array
map.get('circles').push(shape);
}

highlight all routes (google maps) within a specific circle radius

I am using Google Maps Javascript API v3,
What i would like to do is to highlight all routes within a specific circle radius when choosing a point in the map (point coordinates and circle radius are input parameters).
I tried to use the Directions Services and i did manage to display all possible routes when origin and destination points and travelMode are specified and the provideRouteAlternatives option is set to true.
When setting the origin point to be the cirle center, is there way to set multiple destinations points (points on the circle perimeter), and then loop over availables routes and highlight them using Directions Service?
P.S.: i am not trying to draw a circle around a point but to highlight all roads within the circle radius.
Thanks.
This is a just-for-fun answer.
Not really an answer because it really feels like a dirty little hack, and also I am not sure to understand what exactly you are trying to highlight (is it all streets or the results of a Directions request — this is unclear from your question).
But basically, I added 2 maps. The first one is the base map and the other one is positioned on top of the first one, with a border radius, and styles applied.
I then synchronize both maps so that they both move relatively (when panning / zooming).
var myLatlng = new google.maps.LatLng(51.51, -0.12);
var styles = [{
"featureType": "road",
"elementType": "geometry.fill",
"stylers": [{
"color": "#ff3380"
}]
}];
var mapOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var roundedMapOptions = {
zoom: 12,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
disableDefaultUI: true,
scrollwheel: false,
styles: styles
};
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
var roundedMap = new google.maps.Map(document.getElementById("map-rounded"), roundedMapOptions);
google.maps.event.addListener(map, 'drag', function () {
roundedMap.setCenter(map.getCenter());
});
google.maps.event.addListener(roundedMap, 'drag', function () {
map.setCenter(roundedMap.getCenter());
});
google.maps.event.addListener(map, 'idle', function () {
roundedMap.setCenter(map.getCenter());
});
google.maps.event.addListener(map, 'zoom_changed', function () {
roundedMap.setZoom(map.getZoom());
});
Note on the use of the idle event listener:
If you are dragging the map very quickly, sometimes the sync is kind of lost. So with the idle event listener, the maps are re-synced after a drag.
Note that I added the below CSS rule to hide the copyright on the rounded map:
#map-rounded .gm-style-cc {
display: none;
}
This is clearly against Google Maps TOS but since it is still there on the base map, I would think this is a fair or acceptable misuse of the API :)
JSFiddle demo

OpenLayers WMS layer doesn't load

I use the following block of JavaScript to try to show a WMS layer. I'm using OpenLayers 2.8.
The map's base layer (Openstreetmap) shows correctly, it zooms to the correct area, the "pyramid" layer is shown in the layer switcher, but no request to its WMS service is ever made (so the fact that the URL, styles and params are dummies shouldn't matter -- it never even attempts to get them).
OpenLayers does try to get a WMS layer once I pan or zoom far enough so that the Gulf of Guinea is in view (but all my data is in the Netherlands). This suggests a projection problem (WGS84's (0, 0) point is there), but I don't understand why OpenLayers doesn't even try to fetch a map layer elsewhere. My data is in EPSG:3857 (Web Mercator) projection.
/*global $, OpenLayers */
(function () {
"use strict";
$(function () {
$(".map").each(function () {
var div = $(this);
var data_bounds = div.attr("data-bounds");
console.log("data_bounds: " + data_bounds);
if (data_bounds !== "") {
var map = new OpenLayers.Map(div.attr("id"), {
projection: "EPSG:3857"});
var extent = JSON.parse(data_bounds);
var bounds = new OpenLayers.Bounds(
extent.minx, extent.miny,
extent.maxx, extent.maxy);
map.addLayer(
new OpenLayers.Layer.OSM(
"OpenStreetMap NL",
"http://tile.openstreetmap.nl/tiles/${z}/${x}/${y}.png",
{buffer: 0}));
map.addLayer(
new OpenLayers.Layer.WMS(
"pyramid", "http://rasterserver.local:5000/wms", {
layers: "test",
styles: "test"
}, {
singleTile: true,
isBaseLayer: false,
displayInLayerSwitcher: true,
units: 'm'
}));
map.addControl(new OpenLayers.Control.LayerSwitcher());
map.zoomToExtent(bounds);
}
});
});
})();
Edit: the 'data_bounds' console print prints (with some added formatting):
data_bounds: {
"minx": 582918.5701295201,
"miny": 6923595.841021758,
"maxx": 821926.9006116659,
"maxy": 7079960.166533174
}
It zooms to the correct region in the north of the Netherlands, so I don't think the problem is there.
Since posting, I found out that if I don't use the OSM layer, and instead use the WMS layer as baselayer, it works. So perhaps there's some incompatibility with a OSM baselayer and a WMS layer added to it? But then I don't get that it does seem to do something near WGS84 (0, 0).
I eventually managed to fix this by giving the map an explicit maxExtent:
var extent = JSON.parse(data_bounds);
var bounds = new OpenLayers.Bounds(
extent.minx, extent.miny,
extent.maxx, extent.maxy);
var map = new OpenLayers.Map(div.attr("id"), {
projection: "EPSG:3857",
maxExtent: bounds
});
Oddly enough this doesn't limit the user's ability to pan and zoom around the world, but it does make the overlay work...

Categories

Resources