📜 ⬆️ ⬇️

Geocoding addresses into coordinates and geolocation of your current location in OpenLayers

Hi, Habr.

This post will be small, but I hope useful. Today I will talk about how I implemented the search for a place on the map by its address, as well as how I determine the current location of the user. All this is based on OpenLayers 2.

I hope that the reader is already familiar with the basics of working in OpenLayers and a map with layers has already been created. If not, write in the comments, I will try to tell everything in detail.
')


In the first place is geolocation . IMHO, thanks to OL, this issue is not time consuming.

First, create the desired object:

var control = new OpenLayers.Control.Geolocate( bind: false, watch: true, geolocationOptions: { enableHighAccuracy: true, maximumAge: 0, timeout: 15000 }); 


and add it to the map (OpenLayersMap is the actually created map object after the OpenLayers.Map (options) constructor):

 OpenLayersMap.addControl(control); 


With this sorted out, but what's next. Next you need to activate it. Again, it's simple:

 control.activate(); 


And the last thing I added was an event handler when a location was found. To do this, register the event and specify the function to handle this event:

 control.events.on({ "locationupdated": function(e) { OpenLayersFunc.Events.GeolocateOnLocationUpdated(e); } }) 


Now we will prepare a layer to display our elements:

 var layer = new OpenLayers.Layer.Vector('Geolocate', { styleMap: new OpenLayers.StyleMap( new OpenLayers.Style({ fillColor: '#000', fillOpacity: 0.1, strokeWidth: 0}) ) }); OpenLayersMap.addLayer(layer); 


It remains to write the OpenLayersFunc.Events.GeolocateOnLocationUpdated function. The very principle of action is as follows. When the “locationupdated” event fires, our function is called to which the event of this event is passed. And already in this function we are running over it as we want. I tried to comment on the code, so just look:

 var vector = OpenLayersMap.getLayersByName('Geolocate')[0]; vector.removeAllFeatures(); //   (   ) var polygon = OpenLayers.Geometry.Polygon.createRegularPolygon(new OpenLayers.Geometry.Point(e.point.x, e.point.y), e.position.coords.accuracy / 2, 40, 0); var circle = new OpenLayers.Feature.Vector(polygon); //           var point = new OpenLayers.Feature.Vector(e.point, {}, { graphicName: 'cross', strokeColor: '#f00', strokeWidth: 1, fillOpacity: 0, pointRadius: 8 }); //    vector.addFeatures([point, circle]); //       if (OpenLayersFunc.Events.GeolocateFirstRun) { //   ,         pulsate(circle); //   ,   OpenLayersFunc.Events.GeolocateFirstRun = false; } 


The pulsate function adds a pulsation animation to the circle. In the parameter we pass the object of our circle - circle. It looks pretty impressive:
 var pulsate = function(feature) { var point = feature.geometry.getCentroid(); var bounds = feature.geometry.getBounds(); var radius = Math.abs((bounds.right - bounds.left) / 2); var count = 0; var grow = 'up'; var resize = function() { if (count > 16) { clearInterval(window.resizeInterval); } var interval = radius * 0.03; var ratio = interval / radius; switch (count) { case 4: case 12: grow = 'down'; break; case 8: grow = 'up'; break; } if (grow !== 'up') { ratio = -Math.abs(ratio); } feature.geometry.resize(1 + ratio, point); vector.drawFeature(feature); count++; }; window.resizeInterval = window.setInterval(resize, 50, point, radius); }; 


All the code of this implementation under the spoiler:
Geolocation
 var layer = new OpenLayers.Layer.Vector('Geolocate', { styleMap: new OpenLayers.StyleMap( new OpenLayers.Style({ fillColor: '#000', fillOpacity: 0.1, strokeWidth: 0}) ) }); OpenLayersMap.addLayer(layer); var control = new OpenLayers.Control.Geolocate( bind: false, watch: true, geolocationOptions: { enableHighAccuracy: true, maximumAge: 0, timeout: 15000 }); OpenLayersMap.addControl(control); control.activate(); OpenLayersFunc.Events.GeolocateFirstRun = true; OpenLayersFunc.Events.GeolocateOnLocationUpdated = function(e) { var vector = OpenLayersTools.Layers.GetLayerByName('Geolocate'); var pulsate = function(feature) { var point = feature.geometry.getCentroid(); var bounds = feature.geometry.getBounds(); var radius = Math.abs((bounds.right - bounds.left) / 2); var count = 0; var grow = 'up'; var resize = function() { if (count > 16) { clearInterval(window.resizeInterval); } var interval = radius * 0.03; var ratio = interval / radius; switch (count) { case 4: case 12: grow = 'down'; break; case 8: grow = 'up'; break; } if (grow !== 'up') { ratio = -Math.abs(ratio); } feature.geometry.resize(1 + ratio, point); vector.drawFeature(feature); count++; }; window.resizeInterval = window.setInterval(resize, 50, point, radius); }; OpenLayersTools.Layers.ClearLayers(['Geolocate']); var polygon = OpenLayers.Geometry.Polygon.createRegularPolygon(new OpenLayers.Geometry.Point(e.point.x, e.point.y), e.position.coords.accuracy / 2, 40, 0); var circle = new OpenLayers.Feature.Vector(polygon); var point = new OpenLayers.Feature.Vector(e.point, {}, { graphicName: 'cross', strokeColor: '#f00', strokeWidth: 1, fillOpacity: 0, pointRadius: 8 }); vector.addFeatures([point, circle]); if (OpenLayersFunc.Events.GeolocateFirstRun) { pulsate(circle); OpenLayersFunc.Events.GeolocateFirstRun = false; } }; control.events.on({ "locationupdated": function(e) { OpenLayersFunc.Events.GeolocateOnLocationUpdated(e); } }) 


We now turn to a very similar thing - geocoding . I used api from google and have no regrets. Let's start:

First, create another layer to display the marker with popup:

 var layer = new OpenLayers.Layer.Vector('Geocoder', { styleMap: new OpenLayers.StyleMap( new OpenLayers.Style({ externalGraphic: '../images/geocoder_marker.png', graphicWidth: 32, graphicHeight: 32, graphicYOffset: -32 ) }); 


Everything is much simpler here. One function and one from jQuery to make everything beautiful. Create a geocoding object, make a request to Google, get the result and parsim for jquery-ui.autocomplete on the source. And on select, we center the map on this address and add a marker with the address window:

 var geocoder = new google.maps.Geocoder(); //   $('#top-search-field').autocomplete({ //      source: function(request, response) { //     geocoder.geocode({'address': request.term}, function(results, status) { //   response($.map(results, function(item) { //      return { //       autocomplete label: item.formatted_address, value: item.formatted_address, latitude: item.geometry.location.lat(), longitude: item.geometry.location.lng() }; })); }); }, select: function(event, ui) { //     var layer = OpenLayersMap.getLayersByName('Geocoder')[0]; layer.removeAllFeatures(); //     var point_popup = new OpenLayers.LonLat(ui.item.longitude, ui.item.latitude); //    point_popup.transform(new OpenLayers.Projection("EPSG:4326"), OpenLayersMap.getProjectionObject()); //     var point = new OpenLayers.Geometry.Point(ui.item.longitude, ui.item.latitude); //  point.transform(new OpenLayers.Projection("EPSG:4326"), OpenLayersMap.getProjectionObject()); var feature = new OpenLayers.Feature.Vector(point); //   var popup = new OpenLayers.Popup.FramedCloud('geocoder_marker', point_popup, new OpenLayers.Size(200, 50), ui.item.label, null, false, true); //  OpenLayersTools.BaseFunc.CenterMap(ui.item.longitude, ui.item.latitude, 'EPSG:4326'); //    popup.closeOnMove = true; // ,      OpenLayersMap.addPopup(popup); layer.addFeatures(feature); //        } }); 

There’s no need to hang the full code, it’s all from above :)

PS I tried to write this, I do not know if it worked out or not. But still waiting for constructive criticism, wishes :)

Source: https://habr.com/ru/post/166215/


All Articles