Jermaine Subia Jermaine Subia - 1 month ago 11
Javascript Question

Reuse a Google Maps street view inside of a modal

I am developing a web app in Rails. When I open a marker, a modal pops up with a street view in a box. I can open one or two markers, but after that I get an error that WebGL has hit a snag. I have tried to look online for resources but nothing makes sense. See below pics for more info. Any help would be greatly appreciated.

First image with error

second image with error

Here is an image of what my console log looks like:

console log

Here is my JavaScript code in my webapp.

<script type="text/javascript">
var handler = Gmaps.build('Google', {
markers: {
clusterer: {
gridSize: 60,
maxZoom: 20,
styles: [
{
textSize: 10,
textColor: '#ff0000',
url: 'assets/creative/m1.png',
height: 60,
width: 60,
},
{
textSize: 14,
textColor: '#ffff00',
url: 'assets/creative/m2.png',
height: 60,
width: 60,
},
{
textSize: 18,
textColor: '#0000ff',
url: 'assets/creative/m3.png',
width: 60,
height: 60,
},
],
},
},
});

var handler2 = Gmaps.build('Google');
var current;
function initialize() {
handler.buildMap({ internal: {id: 'map'} }, function () {
markers_json = <%= raw @hash.to_json %>;
markers = _.map(markers_json, function (marker_json) {
marker = handler.addMarker(marker_json);
handler.fitMapToBounds();
_.extend(marker, marker_json);
return marker;
});

getLocation();

markers.map(function (elem, index) {
google.maps.event.addListener(elem.getServiceObject(), 'click', function (evt) {
var id = elem.id,
number = elem.number,
name = elem.name,
zipcode = elem.zipcode,
tabid = elem.tabid,
latitude = elem.latitude,
longitude = elem.longitude;

$('.name').html('<h3 class=\'panel-title\'><i class=\'fa fa-id-card\'></i>' + number + '</h3>');
$('.paneltb').html('<thead><tr><th>Panel</th><th>Location</th><th>Tab ID</th><th>Zip Code</th><th>Latitude</th><th>Longitude</th></tr></thead><tbody><tr><td>' + number + '</td><td>' + name + '</td><td>' + tabid + '</td><td>' + zipcode + '</td><td>' + latitude + '</td><td>' + longitude + '</td></tr></tbody>');

pos = new google.maps.LatLng(latitude, longitude);

var div = document.getElementById('map2');
var sv = new google.maps.StreetViewPanorama(div);
sv.setPosition(pos);
sv.setVisible(true);

// find the heading by looking from the google car pos to the venue pos
var service = new google.maps.StreetViewService();
service.getPanoramaByLocation(pos, 50, function (result, status) {
if (status == google.maps.StreetViewStatus.OK)
{
carPos = result.location.latLng;
heading = google.maps.geometry.spherical.computeHeading(carPos, pos);
sv.setPov({ heading: heading, pitch: 0, zoom: 1 });
}
});

$('#myModal').modal('show');
current = elem;
});
});
});
// Create the search box and link it to the UI element.
}

function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(displayOnMap);
} else {
navigator.geolocation.getCurrentPosition(displayOnMapError);
}
}

function displayOnMap(position) {
marker2 = handler.addMarker({
lat: position.coords.latitude,
lng: position.coords.longitude,
picture: {
url: "<%= asset_path 'creative/1499326997_Untitled-2-01.png' %>",
width: 48,
height: 48,
},
infowindow: 'You are Here!',
});
handler.map.centerOn(marker2);
handler.getMap().setZoom(10);
}

function displayOnMapError(position) {
marker2 = handler.addMarker({
lat: 34.0522,
lng: -118.2437,
picture: {
url: "<%= asset_path 'creative/1499326997_Untitled-2-01.png' %>",
width: 48,
height: 48,
},
});
handler.map.centerOn(marker2);
handler.getMap().setZoom(10);
}

initialize();
</script>


This was the original code to get the modal to pop up with the information I needed.

$(".name").html("<h3 class='panel-title'><i class='fa fa-id-card'></i>"+number+"</h3>");
$(".paneltb").html("<thead><tr><th>Panel</th><th>Location</th><th>Tab ID</th><th>Zip Code</th><th>Latitude</th><th>Longitude</th></tr></thead><tbody><tr><td>"+number+"</td><td>"+ name + "</td><td>"+tabid+"</td><td>"+zipcode+"</td><td>"+latitude+"</td><td>"+longitude+"</td></tr></tbody>");

$('#myModal').modal('show');
current = elem;


In order to add the street view inside of the modal the following code was added:

pos = new google.maps.LatLng( latitude, longitude );

var div = document.getElementById('map2');
var sv = new google.maps.StreetViewPanorama(div);
sv.setPosition(pos);
sv.setVisible(true);

// find the heading by looking from the google car pos to the venue pos
var service = new google.maps.StreetViewService();
service.getPanoramaByLocation(pos, 50, function (result, status) {
if (status == google.maps.StreetViewStatus.OK) {
carPos = result.location.latLng;
heading = google.maps.geometry.spherical.computeHeading(carPos, pos);
sv.setPov({ heading: heading, pitch: 0, zoom: 1 });
}
});


In order to pass the current lat and long into the street view, I had to put it inside of the same function that the modal is being called on.

UPDATE

I cannot figure how to set
var sv = new google.maps.StreetViewPanorama(div);
so it is set once and the same map reused for each instance of the modal that is called rather than trying to start and restart a new instance.

Update 2

I cannot figure out how to initially initialize this part:

var sv = new google.maps.StreetViewPanorama(div);


So when I open a modal it does not render a new map it just reuses the same map. I am inclined to write another function but I need some guidance, please.

UPDATE 3

Something else I have noticed is that when I click on one marker it will show the street view filling its square in the modal. When I click on another one sometimes it won't show at all but in most cases, it shows but very tiny in the corner as in this image:

update 3

I also noticed that the code for class
widget-scene-canvas
which comes from Google Maps keeps altering itself from what I originally had it be through my own id styling when I click on more than the first map at separate times.

widget

Answer Source

I figured out that I had more then one problem I had three to be exact. Thanks to https://stackoverflow.com/a/19048363/7039895 I was able to figure out that I needed to resize my map inside the modal each time a modal is opened. The script for that which was placed after the modal was opened is:

$("#myModal").on("shown.bs.modal", function () {
    google.maps.event.trigger(sv, "resize");
});  

The second issue occurred when I noticed that some locations when I opened a modal would render the google street maps while others would render a google street map but it was solid black like this image:

error

What I discovered was that I needed to alter the zoom of the rendered street map to 0 because it was at a 1 zoom from the pov of the car and some lats and longs in my map could not zoom while others could and this all depends on where the google car snapped a photo. Here is the code notice where it says zoom I changed that from a 1 zoom to a 0:

var service = new google.maps.StreetViewService();
        service.getPanoramaByLocation( pos, 50, function(result, status) {
            if (status == google.maps.StreetViewStatus.OK) 
            {   
                carPos = result.location.latLng;
                heading = google.maps.geometry.spherical.computeHeading( carPos, pos );
                sv.setPov( { heading: heading, pitch: 0, zoom: 0 } );
            }
        })

The last thing I needed to fix was the webGL hit a snag error which kept popping up. Upon further investigation on my end I noticed whether I was in the web app or just exploring google maps it was popping up regardless. It seemed to be an error with chrome in general so I took a look at this article in particular https://www.xtremerain.com/fix-rats-webgl-hit-snag-chrome/ I followed the first example and disabled (see below) from the advanced settings.

Use hardware acceleration when available

After that I went back and tested the map and each location opens with the google street map showing and the webgl hit a snag error no longer appeared.

Here is the final code for the map portion of my web app:

var handler = Gmaps.build('Google', {
               markers:
                      {clusterer: {
                        gridSize: 60,
                        maxZoom: 20,
                        styles: [ {
                          textSize: 10,
                          textColor: '#ff0000',
                          url: 'assets/creative/m1.png',
                          height: 60,
                          width: 60 }
                        , {
                          textSize: 14, 
                          textColor: '#ffff00',
                          url:'assets/creative/m2.png',
                          height: 60,
                          width: 60 }
                        , {
                         textSize: 18, 
                         textColor: '#0000ff',
                         url: 'assets/creative/m3.png',
                         width: 60,
                         height: 60}
                        ]}}
            });

var current;
function initialize(){
  handler.buildMap({ internal: {id: 'map'} }, function() {

    markers_json = <%=raw @hash.to_json %>;
    markers = _.map(markers_json, function(marker_json){
      marker = handler.addMarker(marker_json);
      handler.fitMapToBounds();
      _.extend(marker, marker_json);
      return marker;
    });

    getLocation();



    markers.map(function(elem, index) {

      google.maps.event.addListener(elem.getServiceObject(), "click", function(evt) {
        var id = elem.id,
            number = elem.number,
            name = elem.name,
            zipcode = elem.zipcode,
            tabid = elem.tabid,
            latitude = elem.latitude,
            longitude = elem.longitude



         $(".name").html("<h3 class='panel-title'><i class='fa fa-id-card'></i>"+number+"</h3>")
         $(".paneltb").html("<thead><tr><th>Panel</th><th>Location</th><th>Tab ID</th><th>Zip Code</th><th>Latitude</th><th>Longitude</th></tr></thead><tbody><tr><td>"+number+"</td><td>"+ name + "</td><td>"+tabid+"</td><td>"+zipcode+"</td><td>"+latitude+"</td><td>"+longitude+"</td></tr></tbody>")


        pos = new google.maps.LatLng( latitude, longitude );
        var div = document.getElementById('map2');
        var sv = new google.maps.StreetViewPanorama(div);



        sv.setPosition( pos );
        sv.setVisible( true );

        // find the heading by looking from the google car pos to the venue pos
        var service = new google.maps.StreetViewService();
        service.getPanoramaByLocation( pos, 50, function(result, status) {
            if (status == google.maps.StreetViewStatus.OK) 
            {   
                carPos = result.location.latLng;
                heading = google.maps.geometry.spherical.computeHeading( carPos, pos );
                sv.setPov( { heading: heading, pitch: 0, zoom: 0 } );
            }
        })

        $('#myModal').modal('show')

            current = elem;

      $("#myModal").on("shown.bs.modal", function () {
    google.maps.event.trigger(sv, "resize");
});  

        });
    })
  });
    // Create the search box and link it to the UI element.


}
function getLocation(){
  if(navigator.geolocation){
    navigator.geolocation.getCurrentPosition(displayOnMap);
  }
  else{
    navigator.geolocation.getCurrentPosition(displayOnMapError);
  }
};
function displayOnMap(position){

  marker2 = handler.addMarker({
    lat: position.coords.latitude,
    lng: position.coords.longitude,
    picture: {
        url: "<%= asset_path 'creative/1499326997_Untitled-2-01.png' %>",
        width:  48,
        height: 48
        },
    infowindow:  "You are Here!"
  });
  handler.map.centerOn(marker2);
  handler.getMap().setZoom(10);
};

function displayOnMapError(position){

  marker2 = handler.addMarker({
    lat: 34.0522,
    lng: -118.2437,
    picture: {
        url: "<%= asset_path 'creative/1499326997_Untitled-2-01.png' %>",
        width:  48,
        height: 48
        }
  });
  handler.map.centerOn(marker2);
  handler.getMap().setZoom(10);
};




initialize();