在模式中重复使用Google Maps街景视图
我正在开发Rails中的Web应用程序。 当我打开标记时,会弹出一个模式,其中包含一个框中的街景视图。 我可以打开一个或两个标记,但之后我得到一个WebGL遇到障碍的错误。 我试图在网上寻找资源,但没有任何意义。 有关详细信息,请参阅下面的图片。 任何帮助将不胜感激。
第一张图片有错误
这是我的控制台日志的图像:
这是我的webapp中的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 = ; 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('' + number + '
'); $('.paneltb').html('Panel Location Tab ID Zip Code Latitude Longitude ' + number + ' ' + name + ' ' + tabid + ' ' + zipcode + ' ' + latitude + ' ' + longitude + ' '); 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: "", 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: "", width: 48, height: 48, }, }); handler.map.centerOn(marker2); handler.getMap().setZoom(10); } initialize();
这是使模式弹出我需要的信息的原始代码。
$(".name").html(""+number+"
"); $(".paneltb").html("Panel Location Tab ID Zip Code Latitude Longitude "+number+" "+ name + " "+tabid+" "+zipcode+" "+latitude+" "+longitude+" "); $('#myModal').modal('show'); current = elem;
为了在模态内添加街景视图,添加了以下代码:
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 }); } });
为了将当前的lat和long传递到街景中,我不得不把它放在调用模态的相同函数内。
UPDATE
我无法想象如何设置var sv = new google.maps.StreetViewPanorama(div);
所以它被设置一次,并且相同的映射重用于被调用的模态的每个实例,而不是尝试启动和重新启动新实例。
更新2
我无法弄清楚如何初始化这个部分:
var sv = new google.maps.StreetViewPanorama(div);
因此,当我打开一个模态时,它不会渲染新的地图,只会重复使用相同的地图。 我倾向于写另一个函数,但我需要一些指导。
更新3
我注意到的其他事情是,当我点击一个标记时,它将显示街景视图在模态中填充其正方形。 当我点击另一个有时它根本不显示,但在大多数情况下,它显示但在角落中非常小,如在此图像中:
我还注意到,来自谷歌地图的类widget-scene-canvas
的代码在不同时间单击第一张地图时,通过我自己的id样式不断改变自己的原始状态。
我发现我有一个问题,我有三个确切的问题。 感谢https://stackoverflow.com/a/19048363/7039895我能够弄清楚每次打开模态时我需要在模态内调整地图大小。 打开模态后放置的脚本是:
$("#myModal").on("shown.bs.modal", function () { google.maps.event.trigger(sv, "resize"); });
第二个问题发生在我注意到当我打开模态时某些位置会渲染谷歌街道地图而其他地方会渲染谷歌街道地图但是像这个图像那样是纯黑色:
我发现我需要将渲染的街道地图的缩放比例改为0,因为它距离汽车的pov只有1个缩放,而我的地图中的一些拉特和长条无法缩放,而其他人则可以,这一切都取决于谷歌汽车拍了一张照片。 这是代码注意事项,它说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 } ); } })
我需要解决的最后一件事是webGL遇到了一个不断弹出的障碍错误。 经过对我的进一步调查,我注意到我是在网络应用程序还是只是探索谷歌地图,无论如何。 一般来说铬似乎是一个错误,所以我特别看了这篇文章https://www.xtremerain.com/fix-rats-webgl-hit-snag-chrome/我按照第一个例子禁用了(从高级设置看下面)。
可用时使用硬件加速
之后我回去测试了地图,每个位置都打开了谷歌街道地图显示,并且webgl遇到了不再出现的阻碍错误。
这是我的网络应用程序的地图部分的最终代码:
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(""+number+"
") $(".paneltb").html("Panel Location Tab ID Zip Code Latitude Longitude "+number+" "+ name + " "+tabid+" "+zipcode+" "+latitude+" "+longitude+" ") 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();
实际上这个问题与webGL和JS没有任何关系(好吧没有),因为我猜测的是每次点击一个位置时,你都在初始化一个新的webGL实例而不是重用你之前的地图(之前已经初始化),这就是为什么你只能“在webGL遇到障碍之前打开1或2”。
这对于浏览器来说变得非常沉重,所以它决定是时候去吃午饭了。
正如我猜测你要做的是使用ajax来渲染一个新的地图,然后派上用场的是能够破坏之前初始化的地图,但不幸的是,谷歌地图API没有一个用于销毁地图实例的函数,(Mapbox和其他apis都可以)。 但谷歌正式将其解释为:
嗨,大家好,
首先,道歉,到目前为止我们对这个问题一直保持沉默。
接下来,有一个简单的解决方法,即重用Map实例。 如果有一个很好的理由你不能这样做,我很想知道。
我将此标记为无法修复,因为这在技术上很难。 我们不确定我们泄漏了多少个地方:-(另外,我们可能需要引入某种map.destroy()方法。否则,我们怎么知道你是否计划重用地图?Javascript没有析构函数,所以我们无法知道你已经抛弃了对象的引用。
很抱歉成为坏消息的承担者。
因此,您需要确保的是,每次渲染新部分时,您都不会初始化新地图。 但是重新使用你最初初始化的那个。
你的问题住在这里:
var sv = new google.maps.StreetViewPanorama(div);
并且你没有表现出你如何调用弹出窗口,所以我无法真正为你建议一条道路。 如果这对您有意义,请告诉我。