Reputation: 448
I have a google map that shows up on a page, with markers on each location with a different marker based on each locations status.
I want for when a location is updated: the map to be re-rendered for everyone who is viewing it. This means all the markers would update, so no user would be looking at old marker indicators.
How can I achieve this? I tried to use render_Sync
, but apparently render_sync
gem has to load an entire collection seperately. Meaning it tries to render the map as many times as locations there are, which sends too many requests to Google Maps and fails/breaks it.
Upvotes: 2
Views: 637
Reputation: 376
You can use Action Cable to broadcast the coordinates to the UI, save them in some data attributes and poll them from your map script.
You can follow the steps below:
Create a new channel. Lets call it 'locations':
rails g channel locations
Broadcast the latest coordinates as you receive them:
ActionCable.server.broadcast 'locations_channel', { latitude: 'NEW_LATITUDE', longitude: 'NEW_LONGITUDE' }
Once you receive the latest coordinates on the UI, you can set them as data attributes for your map div
like this:
$('#map').data(data);
You can find the code snippet for this part in this gist
Poll the map div
's data attributes at a regular interval and update the marker's position with:
marker.setPosition(latlng)
I have written a step by step guide on Medium on how to do this. You can take a look for more.
Upvotes: 0
Reputation: 7893
Your google map is initialized in your view via Javascript call. You just need to write method which make repeated calls to your controller or other REST server in some time intervals. After each successfull response you will update your markers positions.
Something like that:
<script type="text/javascript">
var handler = Gmaps.build('Google');
var markers = [];
var once = true;
$(document).on('rails_admin.dom_ready', function() {
handler.buildMap({ provider: {maxZoom: 20, zoom: 15}, internal: {id: 'map'}}, function(){
getMarker();
window.setInterval(getMarker, 5000);
});
});
function getMarker() {
$.post('/api/v1/get_position',
{
uuid: '<%= @object.uuid %>'
},
function (data, status) {
handler.removeMarkers(markers);
markers = [];
markers = handler.addMarkers([
{
"lat": data.lat,
"lng": data.lng,
"infowindow": "<%= @object.name %>"
}
]);
if (once) {
handler.fitMapToBounds();
handler.bounds.extendWith(markers);
handler.map.centerOn({ lat: data.lat, lng: data.lng });
once = false;
}
console.log(data);
});
};
</script>
<div style="width: 800px;">
<div id="map" style="width: 800px; height: 600px;"></div>
</div>
Upvotes: 1