Scenario:
Want to create leaflet map with following features.
- Create Marker on Click
- Create a circle with custom radius on the marker point
- Create a rectangle polygon around the center of the circle with custom radius and custom angle of rotation.
- Allows Dragging of the Marker and redraw the polygon on Movement.
Solution :
Step1 : Define a Map for Map in HTML
<div id=”map” style=”position: absolute; height: 100%; width: 100%;”></div>
Step 2: Initialize map
var map = L.map('map').setView([24, 54], 12); mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>'; L.tileLayer( 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© ' + mapLink + ' Contributors', maxZoom: 18, autoPan: true }).addTo(map);
Step 3:
Add a click on event on map to create a marker on clicked point
map.on('click', function (e) { // e.latlng.lat - Latitude of clicked point // e.latlng.lng - longitude of clicked point // call the function with custom radius in meters - 6000 Meters means , 6KM //cla the function with angle required : here it is 32 degrees DrawAll(e.latlng.lat, e.latlng.lng, 6000, 32) });
Step 4 : Now time to create the function
function DrawAll(lat, lng, rad, angles) { //clear old layers ExpressLayers.clearLayers(); //create a marker and add to layer group var marker = L.marker([lat,lng], { draggable: 'true', autoPan: true }).addTo(map); ExpressLayers.addLayer(marker); //create a cirle and add to layer group var circle = L.circle([lat, lng], { color: "white", fillColor: "#f03", fillOpacity: 0.0, radius: rad }).addTo(map); ExpressLayers.addLayer(circle); //prepare data for create a square around with defined angle var centerpoint = [lat, lng]; var retpoint = []; // var angles = 14; // change this variable for desired angle retpoint = rotateboundary(centerpoint , circle.getBounds(), angles); //draw polygon from received coordinates var polygon = L.polygon([retpoint], { color: 'green' }); polygon.addTo(map); ExpressLayers.addLayer(polygon); //create an event to move or redraw in case the marker is dragged to new position marker.on('dragend', function (event) { var marker = event.target; var position = marker.getLatLng(); ExpressLayers.clearLayers(); DrawAll(position.lat, position.lng, 6000, 32) ; // 32 degrees, 60000 radius of 6KM in meters marker.setLatLng(new L.LatLng(position.lat, position.lng), { draggable: 'true' }); ExpressLayers.addLayer(marker); //pan the view along with the marker map.panTo(new L.LatLng(position.lat, position.lng)) }); }
function rotateboundary(CenterPoint, circlebounds, angles) { var ne_lat = circlebounds._northEast.lat; var ne_lon = circlebounds._northEast.lng; var sw_lat = circlebounds._southWest.lat; var sw_lon = circlebounds._southWest.lng; var pointlist = []; var p1 = [sw_lat, ne_lon]; pointlist.push(p1); var p2 = [ne_lat, ne_lon]; pointlist.push(p2); var p3 = [ne_lat, sw_lon]; pointlist.push(p3); var p4 = [sw_lat, sw_lon]; pointlist.push(p4); const res = [] const centerPoint = map.latLngToLayerPoint(CenterPoint) const angle = angles * (Math.PI / 180) for (let i = 0; i < pointlist.length; i++) { const p = map.latLngToLayerPoint(pointlist[i]) // translate to center const p2 = new L.Point(p.x - centerPoint.x, p.y - centerPoint.y) // rotate using matrix rotation const p3 = new L.Point(Math.cos(angle) * p2.x - Math.sin(angle) * p2.y, Math.sin(angle) * p2.x + Math.cos(angle) * p2.y) // translate back to center let p4 = new L.Point(p3.x + centerPoint.x, p3.y + centerPoint.y) // done with that point p4 = map.layerPointToLatLng(p4) res.push(p4) } return res; }
The Final Output of the code will be :
For complete working code of the project refer here : https://github.com/haneefputtur/LeafletRotateCircle/blob/master/leafletrotate.html
Live Demo : https://jsfiddle.net/haneefputtur/vkr1qspe/1/