设置 StreetViewPanorama 的两个属性会导致竞争条件?
Setting two properties of StreetViewPanorama causes race condition?
我正在使用街景视图的 javascript api 打开特定位置的视图。我希望观众既在某个点,又面向某个方向,所以我有这个调用(如 documentation):
panorama.setOptions({
pano: data.location.pano,
pov: mypov
});
我认为从满足这两个选项中获取的图像必须交错或类似的东西,因为大约一半的时间屏幕最终会变成一张以上图像的马赛克:
当我注释掉setPov
时,当然视图朝向错误的方向,但是重叠图像块的问题已经消失。此外,只要用户开始拖动鼠标,街景就会选择正确的图像块并丢弃不正确的图像块。
有什么办法可以避免这种情况吗?或者有没有我可以监听的 "all the images are loaded" 事件,然后触发拖动事件什么的?
编辑:这是一个 jsfiddle 演示:http://jsfiddle.net/p244m3qp/11/
在我的浏览器中,如果我尽可能大地拉伸 "result" 窗格,它会显示大约 1/3 到 1/2 动画帧的 "mosaic" 行为。
我想出了如何防止你的错误。
http://jsfiddle.net/wf9a5m75/p244m3qp/31/
重点是在后台预加载街景。
首先,您需要创建两个全景divs。
<script src="http://maps.googleapis.com/maps/api/js?language=en"></script>
<div id="err"></div>
<div id="pv-container">
<div id="backscreen"></div>
<div id="map-canvas"></div>
</div>
与 CSS. 完全重叠
#pv-container {
position: relative;
height: 500px;
width: 100%;
}
#map-canvas {
border: solid thick #ccc;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
#backscreen {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
border: solid thick red;
}
您需要先更改背景的全景位置(pano 和 pov),然后设置为 map-canvas div。
那时,您需要更改背景的标题(或可能是间距)。
这会在 Google 地图 API 中生成缓存图像(我猜)。
function initialize() {
var loc = {
lat: 38.9002138,
lng: -77.0364319
},
pov = {
heading: 180,
pitch: -5
},
svService = new google.maps.StreetViewService(),
panorama = new google.maps.StreetViewPanorama(
document.getElementById('map-canvas')),
backscreen = new google.maps.StreetViewPanorama(
document.getElementById('backscreen')),
counter = 0;
function updatePano(data, status) {
if (status === google.maps.StreetViewStatus.OK) {
var opts = {
pano: data.location.pano,
pov: {heading: pov.heading + 120 * (counter % 3), pitch: pov.pitch}
};
backscreen.setOptions(opts);
backscreen.changed = function(key) {
if (key === 'status' && backscreen.get('status') === 'OK') {
var opts2 = Object.create(opts);
opts2.heading += 5;
backscreen.setOptions(opts2);
setTimeout(function() {
panorama.setOptions(opts);
}, 100);
}
}
} else {
document.getElementById('err').textContent = "Failed to get panorama";
}
counter = (counter + 1) % 15;
}
setInterval(function() {
svService.getPanorama({
location: {
lat: loc.lat + (counter * 0.0001),
lng: loc.lng
},
radius: 35
}, updatePano);
}, 3000);
}
initialize();
@wf9a5m75 的回答对我来说不太有用,但它引导我朝着正确的方向前进,这最终在 Chrome 中起作用:我替换了单个调用
panorama.setOptions({
pano: data.location.pano,
pov: mypov
});
有两个强制串行调用:
panorama.setPano(pano);
panorama.changed = function(key) {
if (key === 'status') {
// Just listen once!
panorama.changed = function() {};
panorama.setPov(mypov);
}
};
所以加载需要两倍的时间,但至少它看起来并不可怕......
编辑: 看起来这是一个 known bug - 看起来你可以减少竞争条件的命中率,但不能真正阻止它。 :(
我正在使用街景视图的 javascript api 打开特定位置的视图。我希望观众既在某个点,又面向某个方向,所以我有这个调用(如 documentation):
panorama.setOptions({
pano: data.location.pano,
pov: mypov
});
我认为从满足这两个选项中获取的图像必须交错或类似的东西,因为大约一半的时间屏幕最终会变成一张以上图像的马赛克:
当我注释掉setPov
时,当然视图朝向错误的方向,但是重叠图像块的问题已经消失。此外,只要用户开始拖动鼠标,街景就会选择正确的图像块并丢弃不正确的图像块。
有什么办法可以避免这种情况吗?或者有没有我可以监听的 "all the images are loaded" 事件,然后触发拖动事件什么的?
编辑:这是一个 jsfiddle 演示:http://jsfiddle.net/p244m3qp/11/ 在我的浏览器中,如果我尽可能大地拉伸 "result" 窗格,它会显示大约 1/3 到 1/2 动画帧的 "mosaic" 行为。
我想出了如何防止你的错误。 http://jsfiddle.net/wf9a5m75/p244m3qp/31/
重点是在后台预加载街景。
首先,您需要创建两个全景divs。
<script src="http://maps.googleapis.com/maps/api/js?language=en"></script>
<div id="err"></div>
<div id="pv-container">
<div id="backscreen"></div>
<div id="map-canvas"></div>
</div>
与 CSS. 完全重叠
#pv-container {
position: relative;
height: 500px;
width: 100%;
}
#map-canvas {
border: solid thick #ccc;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
#backscreen {
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
border: solid thick red;
}
您需要先更改背景的全景位置(pano 和 pov),然后设置为 map-canvas div。 那时,您需要更改背景的标题(或可能是间距)。 这会在 Google 地图 API 中生成缓存图像(我猜)。
function initialize() {
var loc = {
lat: 38.9002138,
lng: -77.0364319
},
pov = {
heading: 180,
pitch: -5
},
svService = new google.maps.StreetViewService(),
panorama = new google.maps.StreetViewPanorama(
document.getElementById('map-canvas')),
backscreen = new google.maps.StreetViewPanorama(
document.getElementById('backscreen')),
counter = 0;
function updatePano(data, status) {
if (status === google.maps.StreetViewStatus.OK) {
var opts = {
pano: data.location.pano,
pov: {heading: pov.heading + 120 * (counter % 3), pitch: pov.pitch}
};
backscreen.setOptions(opts);
backscreen.changed = function(key) {
if (key === 'status' && backscreen.get('status') === 'OK') {
var opts2 = Object.create(opts);
opts2.heading += 5;
backscreen.setOptions(opts2);
setTimeout(function() {
panorama.setOptions(opts);
}, 100);
}
}
} else {
document.getElementById('err').textContent = "Failed to get panorama";
}
counter = (counter + 1) % 15;
}
setInterval(function() {
svService.getPanorama({
location: {
lat: loc.lat + (counter * 0.0001),
lng: loc.lng
},
radius: 35
}, updatePano);
}, 3000);
}
initialize();
@wf9a5m75 的回答对我来说不太有用,但它引导我朝着正确的方向前进,这最终在 Chrome 中起作用:我替换了单个调用
panorama.setOptions({
pano: data.location.pano,
pov: mypov
});
有两个强制串行调用:
panorama.setPano(pano);
panorama.changed = function(key) {
if (key === 'status') {
// Just listen once!
panorama.changed = function() {};
panorama.setPov(mypov);
}
};
所以加载需要两倍的时间,但至少它看起来并不可怕......
编辑: 看起来这是一个 known bug - 看起来你可以减少竞争条件的命中率,但不能真正阻止它。 :(