Отключить перетаскивание на Google Map Javascript пользовательских элементов управления

1

Я хочу создать собственный пользовательский элемент управления Google, используя API Javascript.

Элемент управления - кнопка "добавить путевую точку". Предполагается, что пользователь сможет перетащить элемент управления, заставив маркер появиться у указателя мыши, и поместите этот маркер на карту.

Предполагаемое поведение почти идентично существующей функции pegman.

Проблема в том, что элементы управления картой Google, похоже, взаимодействуют с перетаскиванием, даже когда перетаскивание явно отключено, как показано ниже.

В примере кода. В первый раз, когда я нажимаю и перетаскиваю, он работает по назначению. Во второй раз, когда я нажимаю и перетаскиваю, я получаю значок "без перетаскивания", и элемент управления порождает призрак. В третий раз я перетаскиваю, он снова работает. При следующем перетаскивании "нет перетаскивания". Последовательность продолжается, при работе с нечетными перетаскиваниями и даже при перетаскивании.

Вот что я считаю соответствующим разделом:

<div id="map"></div>
<script>
    var spawning = false;
    var inProgress = false;
    var waypointSpawner;
    var targetLat;
    var targetLng;

    function initMap()
    {
        map = new google.maps.Map(document.getElementById('map'), {
            center: {lat: 0.0000, lng: 0.0000},
            zoom: 2
        });

        // Create the DIV to hold the control and call the CenterControl()
        // constructor passing in this DIV.
        var centerControlDiv = document.createElement('div');
        var centerControl = new CenterControl(centerControlDiv, map);

        centerControlDiv.index = 1;
        map.controls[google.maps.ControlPosition.LEFT_TOP].push(centerControlDiv);
    }

    function CenterControl(controlDiv, map) {

        // Set CSS for the control border.
        var controlUI = document.createElement('div');
        controlUI.style.backgroundColor = '#fff';
        controlUI.style.border = '2px solid #fff';
        controlUI.style.borderRadius = '3px';
        controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
        controlUI.style.cursor = 'pointer';
        controlUI.style.marginBottom = '22px';
        controlUI.style.width = '40px';
        controlUI.style.height = '50px';
        controlUI.style.opacity = "0.7";
        controlUI.style.backgroundImage = "url('create_waypoint_icon.png')";
        controlUI.title = 'Add Waypoint';
        controlUI.draggable = "false";


    //controlDiv.draggable = "false";
    controlDiv.appendChild(controlUI);
    }

Мне не удалось заставить вышеуказанный код работать в jsfiddle, но есть еще несколько примеров, иллюстрирующих проблему.

http://jsfiddle.net/maunovaha/jptLfhc8/

Попытка перетащить синие и зеленые квадраты в верхнем левом углу карты приводит к некоторому непреднамеренному поведению. В зависимости от вашего уровня масштабирования и несколько случайным образом вы получите множество различных результатов -

1 - Ничего не происходит. Указатель остается как палец и движется нормально.
2 - Указатель пальца изменяется на "нет перетаскивания", но в противном случае движется нормально.
3 - Указатель пальца меняется на "нет перетаскивания" и сине-зеленый полупрозрачный виджет "вставить".
4 - Указатель пальца меняется на "нет перетаскивания", и либо синяя, либо зеленая половина виджета (в зависимости от вашего выбора) идет с ним.

Такое поведение также несколько очевидно в примере кода управления Google:
https://developers.google.com/maps/documentation/javascript/examples/control-custom

В этом случае, когда текст выделен, вы получаете значок "без перетаскивания". Родительский элемент управления не может быть выбран, что является желаемой целью.

Я считаю, что пользовательский контроль приобретает какой-то статус "фокуса", а щелчок снова очищает фокус. Такое поведение проявляется в примере "зеленый/синий". Может быть, контроль "подсвечивается" каким-то образом?

Я попытался реализовать решения, приведенные в разделе Как я могу сделать div неизбираемым? без эффекта. Я также пробовал различные способы сделать div неразборчивым в коде, но это, похоже, не оказало никакого влияния.

Я также попытался имитировать щелчки мыши на других частях программы и дважды щелкнул элемент управления, чтобы изменить статус фокуса/выделения, но, похоже, API фактически не выполняет клики, а генерирует из них только события. Я не мог найти способ вызвать "настоящий" клик. Ручное нажатие, а затем перетаскивание и перетаскивание.

Я также попытался сделать управление перетаскиваемым, но у него все еще есть указатель мыши "без перетаскивания" даже при перетаскивании.

  • 0
    это долго, не может ли оно быть сжатым?
  • 0
    Я считаю, что я удалил столько, сколько смог, оставив соответствующий контекст.
Теги:
google-maps-api-3
custom-controls

1 ответ

0

Если я правильно понимаю, что вы говорите, вы хотите, чтобы вы могли перетащить маркер на карту, извне, и поместить точку в эту позицию.

У меня есть следующее решение, которое делает это.

Сначала нам нужно построить карту:

function buildMap() {
        var g = google.maps;
        var mapOptions = {        
        center: new g.LatLng(52.052491, 9.84375),
        zoom: 4,
        mapTypeId: g.MapTypeId.ROADMAP,
        streetViewControl: false,
        panControl: false
      };
      map = new g.Map(document.getElementById("map"), mapOptions);
      iw = new g.InfoWindow();
      g.event.addListener(map, "click", function() {
        if (iw) iw.close()
      });
      drag_area = document.getElementById("markers");
      var b = drag_area.getElementsByTagName("div");
      b[0].onmousedown = initDrag
      dummy = new DummyOView()
    }

Мы создаем стандартную карту и добавляем такие функции, как infoWindows, для отображения lat lng при добавлении маркера.

Кроме того, мы получаем место, где хранится маркер, и onMouseDown вызывает функцию (в ближайшее время).

Мы используем b[0] поскольку мы получаем первый набор тегов <div> в методе ниже, здесь находится значок перетаскивания:

<div id="markers">
  <div id="m1" class="drag" style="left:0; background-image: url('https://maps.gstatic.com/mapfiles/ms/icons/ltblue-dot.png')">
  </div>
</div>

DummyOView - это карта OverlayView, которая позволяет нам перемещаться по карте и захватывать координаты и положение. Дополнительная информация о SO + credit to: Дополнительная информация

function DummyOView() {
  this.setMap(map);
  this.draw = function() {}
}

DummyOView.prototype = new google.maps.OverlayView();

Функция initDrag - это то, где большая часть работы выполнена, это довольно длительная функция, поэтому я прокомментировал код, любые вопросы по разъяснению просто добавляют комментарий.

//function that allows us to drag the marker from the div to the map
function initDrag(e) {
  //allows us to drag the marker and keep record of the clientX client Y coordinates
  var j = function(e) {
    var a = {};
    if (!e) var e = window.event;
    a.x = e.clientX;
    a.y = e.clientY
    return a
  };
  //function called whenever the mouse moves. this will keep track of the marker as we move around
  var k = function(e) {
    //check to ensure that the object is of class drag - otherwise we could drag everything
    if (obj && obj.className == "drag") {
      var i = j(e),
        deltaX = i.x - l.x,
        deltaY = i.y - l.y;
      obj.style.left = (obj.x + deltaX) + "px";
      obj.style.top = (obj.y + deltaY) + "px";
      obj.onmouseup = function() {
        //get the information to check to see if the dragObj is on the map on mouse up
        var a = map.getDiv(),
          mLeft = a.offsetLeft,
          mTop = a.offsetTop,
          mWidth = a.offsetWidth,
          mHeight = a.offsetHeight;
        var b = drag_area.offsetLeft,
          areaTop = drag_area.offsetTop,
          oWidth = obj.offsetWidth,
          oHeight = obj.offsetHeight;
        //check to see if obj is in bounds of map div X and Y
        var x = obj.offsetLeft + b + oWidth / 2;
        var y = obj.offsetTop + areaTop + oHeight / 2;
        if (x > mLeft && x < (mLeft + mWidth) && y > mTop && y < (mTop + mHeight)) {
          var c = 1;
          var mapTemp = google.maps;
          var point = new mapTemp.Point(x - mLeft - c, y - mTop + (oHeight / 2));
          var proj = dummy.getProjection();
          var latlng = proj.fromContainerPixelToLatLng(point);
          var backImage = obj.style.backgroundImage.slice(4, -1).replace(/"/g, "");
          createDraggedMarker(latlng, backImage);
          fillMarker(backImage)
        }
      }
    }
    return false
  };

  //assign the event to a windows event
  obj = e.target ? e.target : e.srcElement;
  //if the object where the event took place is not called drag cancel the event
  if (obj.className != "drag") {
    if (e.cancelable) e.preventDefault();
    obj = null;
    return
  } else {
    z_index += 1;
    obj.style.zIndex = z_index.toString();
    obj.x = obj.offsetLeft;
    obj.y = obj.offsetTop;

    var l = j(e); //get the initial position of the marker relative to the client

    document.onmousemove = k;
    //if we lift the mouse up outside the map div set to null and leave where it is
    document.onmouseup = function() {
      document.onmousemove = null;
      document.onmouseup = null;
      if (obj) obj = null
    }
  }
  return false
}

Обобщенная эта функция вызывается всякий раз, когда мышь была нажата и перетащена. Он зарегистрировал начальную позицию и позиции div карты и проверил, когда onmouseup проверяет, находится ли текущая позиция мыши над разделителем карты. Если это так, мы создаем маркер на карте и снова добавляем значок маркера в div, чтобы разрешить краху.

//when the marker is dragged onto the map
//we call this function to create a marker on the map
function createDraggedMarker(position, iconImage) {
  var mapLocal = google.maps;
  var icon = {
    url: iconImage,
    size: new mapLocal.Size(32, 32),
    anchor: new mapLocal.Point(15, 32)
  };
  var marker = new mapLocal.Marker({
    position: position,
    map: map,
    clickable: true,
    draggable: true,
    crossOnDrag: false,
    optimized: false,
    icon: icon,
    zIndex: highestOrder()
  });

  mapLocal.event.addListener(marker, "click", function() {
    actual = marker;
    var lat = actual.getPosition().lat();
    var lng = actual.getPosition().lng();
    var innerHtml = "<div class='infowindow'>" + lat.toFixed(6) + ", " + lng.toFixed(6) + "<\/div>";
    iw.setContent(innerHtml);
    iw.open(map, this)
  });
  mapLocal.event.addListener(marker, "dragstart", function() {
    if (actual == marker) iw.close();
    z_index += 1;
    marker.setZIndex(highestOrder())
  })
}

Повторное добавление маркера в div

//Used to replace the marker
//once we have moved it from its div
function fillMarker(a) {
  var div = document.createElement("div");
  div.style.backgroundImage = "url(" + a + ")";
  var padding;
  if (obj.id == "m1") {
    padding = "0px"
  }
  div.style.left = padding;
  div.id = obj.id;
  div.className = "drag";
  div.onmousedown = initDrag;
  drag_area.replaceChild(div, obj);
  obj = null
}

JSfiddle вы можете использовать: https://jsfiddle.net/q3wjrpdw/7/

Любые вопросы, не стесняйтесь спрашивать.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню