3

Using the Google Earth plugin, I want to be able to allow the user to select placemarks on the ground while the camera is moving, but am not sure how this is possible. It seems that when you call setAbstractView(), even with the flyToSpeed set to SPEED_TELEPORT, the Google Earth plugin ignores any mouse down events except for those to the GEGlobe.

Here's the code, altered slightly (from http://code.google.com/apis/ajax/playground/#draggable_placemark) to illustrate my issue:

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) {
}

​ If you comment out line 56, where tick() is called at each frameend, everything works as in the unaltered code: you can successfully drag the place mark. But when line 56 is in, you can't. So the problem is really with setAbstractView keeping mousedown events from propagating to either the globe or whatever placemark or feature was being clicked.

Any ideas? Is there a workaround for this?

4

1 回答 1

0

该问题不是由setAbstractView方法引起的,而是由于对tick方法的重复调用 via引起的framend

为了解释,您已将该tick方法设置为事件的事件处理程序frameend。然后tick方法立即更新视图,触发frameend事件,无限循环......

这种模式会导致浏览器消息循环出现问题,实际上它会阻止其他拖动事件。把它想象成一个导致死锁的非常紧密的循环。要使用它,您可以使用setTimeout值 0 来执行代码。这样,在处理所有其他待处理的拖动消息之前,不会处理动画。

关键部分是对您的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);
};

在这里,我为您制作了一个完整的示例http://jsfiddle.net/fraser/JFLaT/

我对其进行了测试,它在 Windows 8 上的 Chrome、IE、Firefox 和 OSX 上的 Chrome、Safari、Firefox 中运行。

于 2013-12-15T23:48:45.337 回答