简体   繁体   English

在模式中重复使用Google地图街景视图

[英]Reuse a Google Maps street view inside of a modal

I am developing a web app in Rails. 我正在开发Rails中的Web应用程序。 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. 我可以打开一个或两个标记,但之后我得到一个WebGL遇到障碍的错误。 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 第一张图片有错误

第二张图片有错误

Here is an image of what my console log looks like: 这是我的控制台日志的图像:

控制台日志

Here is my JavaScript code in my webapp. 这是我的webapp中的JavaScript代码。

<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. 为了将当前的lat和long传递到街景中,我不得不把它放在调用模态的相同函数内。

UPDATE UPDATE

I cannot figure how to set var sv = new google.maps.StreetViewPanorama(div); 我无法想象如何设置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 更新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 更新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: 当我点击另一个有时它根本不显示,但在大多数情况下,它显示但在角落中非常小,如在此图像中:

更新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-scene-canvas的代码在我不同时间点击第一张地图时,通过我自己的id样式不断改变自己的状态。

小部件

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. 感谢https://stackoverflow.com/a/19048363/7039895我能够弄清楚每次打开模态时我需要在模态内调整地图大小。 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: 第二个问题发生在我注意到当我打开模态时某些位置会渲染谷歌街道地图而其他地方会渲染谷歌街道地图但是像这个图像那样是纯黑色:

错误

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. 我发现我需要将渲染的街道地图的缩放比例改为0,因为它距离汽车的pov只有1个缩放,而我的地图中的一些拉特和长条无法缩放而其他人可以缩放,这一切都取决于谷歌汽车拍了一张照片。 Here is the code notice where it says zoom I changed that from a 1 zoom to a 0 : 这是代码注意事项,它说zoom我从1变焦变为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. 我需要解决的最后一件事是webGL遇到一个不断弹出的障碍错误。 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. 一般来说铬似乎是一个错误,所以我特别看了这篇文章https://www.xtremerain.com/fix-rats-webgl-hit-snag-chrome/我按照第一个例子禁用了(从高级设置中看到)。

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. 之后,我回去测试了地图,每个位置都打开了谷歌街道地图显示,并且webgl点击了不再出现的障碍错误。

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();

This problem actually, has nothing to do with webGL and JS, (well sort of not), because what I'm guessing is that each time you click on a location, you're initialising a new webGL instance and not reusing your previous map (that was initialised before), which his why you can only "open 1 or 2 before webGL hits a snag". 实际上这个问题与webGL和JS没有任何关系(好吧没有),因为我猜的是每次点击一个位置时,你都会初始化一个新的webGL实例而不是重用你以前的地图(之前已初步确定),这就是为什么你只能“在webGL遇到障碍之前打开1或2”。

And this becomes incredibly heavy for the browser, so it decides it's time to go for lunch. 这对浏览器来说变得非常沉重,所以它决定是时候去吃午饭了。

As I'm guessing what you're trying to do is use ajax to render a new map, and what would come in handy then is to be able to destroy the map that was initialised before, but unfortunately, Google maps API do not have a function for destroying a map instance, (Mapbox and other apis do). 因为我猜你要做的是使用ajax渲染一个新的地图,然后派上用场的是能够破坏之前初始化的地图,但不幸的是,谷歌地图API没有用于销毁地图实例的函数,(Mapbox和其他apis)。 But google officially explains it as: 但谷歌正式将其解释为:

Hi everyone, 嗨,大家好,

First, apologies that we've been silent on this issue up to now. 首先,道歉,到目前为止我们对这个问题一直保持沉默。

Next, there's an easy work around, which is to reuse your Map instances. 接下来,有一个简单的解决方法,即重用Map实例。 If there's a good reason why you can't do this I'd love to know. 如果有一个很好的理由你不能这样做,我很想知道。

I'm labeling this as won't fix, because this is technically difficult. 我将此标记为无法修复,因为这在技术上很难。 We're not really sure in how many places we're leaking :-( Additionally, we'd probably need to introduce some sort of map.destroy() method. Otherwise, how are we to know whether you're planning to reuse the map? Javascript doesn't have destructors, so we can't know you've thrown away your reference to the object. 我们不确定我们泄漏了多少个地方:-(另外,我们可能需要引入某种map.destroy()方法。否则,我们怎么知道你是否计划重用地图?Javascript没有析构函数,所以我们无法知道你已经抛弃了对象的引用。

Sorry to be the bearer of bad news. 很抱歉成为坏消息的承担者。

So what you need to make sure of is, that you're not initialising a new map each time you render a new partial. 因此,您需要确保的是,每次渲染新部分时,您都不会初始化新地图。 But instead reuse the one you initialised at first. 但是重新使用您最初初始化的那个。

Your problem lives here: 你的问题住在这里:

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

And you're not showing much of how you're calling the pop-up, so I can't really suggest a path for you. 而且你没有表现出你如何调用弹出窗口,所以我无法真正为你建议一条道路。 Let me know if this makes sense to you. 如果这对您有意义,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM