Javascript setAbstractView()防止鼠标向下事件传播到KmlFeatures
使用Google Earth插件,我希望能够允许用户在相机移动时选择地面上的地点标记,但不确定这是如何实现的。似乎当您调用setAbstractView()时,即使将flyToSpeed设置为SPEED_TELEPORT,Google Earth插件也会忽略任何鼠标按下事件,除了那些到GEGlobe的事件 下面是代码,稍作修改(从)以说明我的问题:Javascript setAbstractView()防止鼠标向下事件传播到KmlFeatures,javascript,kml,google-earth-plugin,Javascript,Kml,Google Earth Plugin,使用Google Earth插件,我希望能够允许用户在相机移动时选择地面上的地点标记,但不确定这是如何实现的。似乎当您调用setAbstractView()时,即使将flyToSpeed设置为SPEED_TELEPORT,Google Earth插件也会忽略任何鼠标按下事件,除了那些到GEGlobe的事件 下面是代码,稍作修改(从)以说明我的问题: var ge; var placemark; var dragInfo = null; var la; var lat = 37; var lon
var ge;
var placemark;
var dragInfo = null;
var la;
var lat = 37;
var lon = -122;
google.load("earth", "1");
function init() {
google.earth.createInstance('map3d', initCallback, failureCallback);
}
function tick() {
la.set(lat, lon,
0, // altitude
ge.ALTITUDE_RELATIVE_TO_GROUND,
0, // heading
0, // straight-down tilt
5000 // range (inverse of zoom)
);
ge.getView().setAbstractView(la);
lon = lon + 0.00000001;
}
function initCallback(instance) {
ge = instance;
ge.getWindow().setVisibility(true);
// add a navigation control
ge.getNavigationControl().setVisibility(ge.VISIBILITY_AUTO);
// add some layers
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, true);
ge.getLayerRoot().enableLayerById(ge.LAYER_ROADS, true);
// create the placemark
placemark = ge.createPlacemark('');
var point = ge.createPoint('');
point.setLatitude(lat);
point.setLongitude(lon);
placemark.setGeometry(point);
// add the placemark to the earth DOM
ge.getFeatures().appendChild(placemark);
// look at the placemark we created
la = ge.createLookAt('');
placemark.setName('Drag Me!');
ge.getOptions().setFlyToSpeed(ge.SPEED_TELEPORT);
tick();
// Comment this next line out and the drag works as expected.
google.earth.addEventListener(ge, "frameend", tick);
// listen for mousedown on the window (look specifically for point placemarks)
google.earth.addEventListener(ge.getWindow(), 'mousedown', function(event) {
console.log("target type = " + event.getTarget().getType());
if (event.getTarget().getType() == 'KmlPlacemark' &&
event.getTarget().getGeometry().getType() == 'KmlPoint') {
//event.preventDefault();
var placemark = event.getTarget();
dragInfo = {
placemark: event.getTarget(),
dragged: false
};
}
});
// listen for mousemove on the globe
google.earth.addEventListener(ge.getGlobe(), 'mousemove', function(event) {
if (dragInfo) {
event.preventDefault();
var point = dragInfo.placemark.getGeometry();
point.setLatitude(event.getLatitude());
point.setLongitude(event.getLongitude());
dragInfo.dragged = true;
}
});
// listen for mouseup on the window
google.earth.addEventListener(ge.getWindow(), 'mouseup', function(event) {
if (dragInfo) {
if (dragInfo.dragged) {
// if the placemark was dragged, prevent balloons from popping up
event.preventDefault();
}
dragInfo = null;
}
});
document.getElementById('installed-plugin-version').innerHTML =
ge.getPluginVersion().toString();
}
function failureCallback(errorCode) {
}
如果注释掉第56行,其中在每个frameend调用tick(),则所有操作都与未更改的代码中的操作相同:您可以成功拖动位置标记。但是当第56行进入时,你不能。因此,setAbstractView的问题在于防止鼠标向下的事件传播到地球或任何正在单击的地点标记或功能
有什么想法吗?有解决办法吗 问题不是由
setAbstractView
方法引起的,而是由于通过framend
重复调用tick
方法引起的
为了解释,您已经将勾选
方法设置为frameend
事件的事件处理程序。
然后tick方法立即更新视图,无限触发frameend
事件
此模式导致浏览器消息循环出现问题,实际上它阻止了其他拖动事件。把它想象成一个导致死锁的非常紧密的循环。要使用它,可以使用值为0的setTimeout
来执行代码。这样,在处理所有其他挂起的拖动消息之前,不会处理动画
关键部分是对tick()
方法的修改
function tick() {
// prevent deadlock
setTimeout(function () {
la.set(lat, lon, 0, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 0, 5000);
ge.getView().setAbstractView(la);
lon += 0.00001;
}, 0);
};
在这里,我为大家做了一个完全有效的例子
我测试了它,它在Chrome、IE、Windows 8上的Firefox和OSX上的Chrome、Safari、Firefox中工作。只是想确定它是否与bug有关-什么浏览器显示了这种行为?我在Safari、Firefox和Chrome中复制了它,并鼓励其他人也尝试一下。只需将代码块复制并粘贴到谷歌代码游乐场: