setAbstractView() предотвращает распространение событий mousedown в KmlFeatures

Используя плагин Google Earth, я хочу, чтобы пользователь мог выбирать метки на земле во время движения камеры, но я не уверен, как это возможно. Кажется, что когда вы вызываете setAbstractView(), даже если для flyToSpeed ​​установлено значение SPEED_TELEPORT, подключаемый модуль Google Планета Земля игнорирует любые события нажатия мыши, за исключением событий, связанных с GEGlobe.

Вот слегка измененный код (из http://code.google.com/apis/ajax/playground/#draggable_placemark), чтобы проиллюстрировать мою проблему:

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, где в конце каждого кадра вызывается tick(), все работает как в неизмененном коде: можно успешно перетаскивать метку места. Но когда есть строка 56, вы не можете. Таким образом, проблема действительно заключается в том, что setAbstractView не позволяет событиям mousedown распространяться либо на земной шар, либо на любую метку или функцию, по которой щелкнули.

Есть идеи? Есть ли обходной путь для этого?


person Dylan    schedule 17.10.2013    source источник
comment
Просто пытаюсь выяснить, связано ли это с ошибкой - какие браузеры отображают такое поведение?   -  person Qantas 94 Heavy    schedule 21.10.2013
comment
Я воспроизвел его в Safari, Firefox и Chrome и призываю всех остальных тоже попробовать его. Просто скопируйте и вставьте блок кода в Google Code Playground: code.google.com/apis. /ajax/игровая площадка/#draggable_placemark   -  person Dylan    schedule 21.10.2013


Ответы (1)


Проблема вызвана не методом setAbstractView, а повторными вызовами метода tick через 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/.

Я протестировал его, и он работает в Chrome, IE, Firefox в Windows 8 и Chrome, Safari, Firefox в OSX.

person Fraser    schedule 15.12.2013