简体   繁体   English

禁用对Google Map Javascript自定义控件的拖动

[英]Disable drag on Google Map Javascript custom controls

I want to create a Google map custom control using the Javascript API. 我想使用Javascript API创建Google地图自定义控件。

The control is an 'add waypoint' button. 该控件是一个“添加航点”按钮。 The user is supposed to be able to drag from the control, causing a marker to appear at the mouse pointer, and drop this marker on to the map. 应该使用户能够从控件中拖动,使标记出现在鼠标指针上,并将该标记放到地图上。

The intended behavior is nearly identical to the existing pegman feature. 预期的行为与现有的衣夹人功能几乎相同。

The problem is that the Google map controls seem to interact with drag, even when the drag has been explicitly disabled, as seen below. 问题在于,即使拖动已被明确禁用,Google地图控件也似乎与拖动交互,如下所示。

In the example code, The first time I click and drag, it works as intended. 在示例代码中,第一次单击并拖动时,它可以正常工作。 The second time I click and drag, I get a 'no drag' icon and the control spawns a ghost of itself. 第二次单击并拖动时,我得到一个“不拖动”图标,该控件会产生一个幽灵。 The third time I drag, it's working again. 我第三次拖动,它又开始工作了。 On the next drag, there's a 'no drag'. 在下一次拖动时,将出现“无拖动”。 The sequence continues, with odd drags working, and even drags failing. 序列继续进行,奇数拖曳起作用,甚至拖曳失败。

Here's what I believe to be the relevant section: 我认为这是相关的部分:

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

I was unable to get the above code to work in jsfiddle, but there are a couple of other examples that illustrate the problem. 我无法使上面的代码在jsfiddle中工作,但是还有两个其他示例可以说明问题。

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

Attempting to drag and drop the blue and green squares in the top left of the map results in some unintended behavior. 尝试拖放地图左上方的蓝色和绿色方块会导致某些意外行为。 Depending on your zoom level, and somewhat randomly, you will get a variety of different outcomes - 根据您的缩放级别(有些随机),您会得到各种不同的结果-

1 - Nothing happens. 1-什么也没发生。 The pointer remains as a finger and moves normally. 指针保持为手指并正常移动。
2 - The finger pointer changes to a 'no drag' but otherwise moves normally. 2-手指指针变为“无阻力”,否则将正常移动。
3 - The finger pointer changes to a 'no drag' and a blue-and green semi-transparent 'to-paste' widget. 3-手指指针变为“无拖动”以及蓝色和绿色的半透明“粘贴”窗口小部件。
4 - The finger pointer changes to a 'no drag', and either the blue or green half of the widget (depending on your selection) goes with it. 4-手指指针变为“无阻力”,并且小部件的蓝色或绿色部分(取决于您的选择)与之一起使用。

This behavior is also somewhat evident in the Google control example code: 这种行为在Google控件示例代码中也很明显:
https://developers.google.com/maps/documentation/javascript/examples/control-custom https://developers.google.com/maps/documentation/javascript/examples/control-custom

In this instance, when the text is highlighted, you get the 'no drag' icon. 在这种情况下,当文本突出显示时,您将获得“不拖动”图标。 The parent control doesn't appear to be selectable, which is the desired goal. 父控件似乎不是可选的,这是期望的目标。

I believe that the custom control is acquiring some kind of 'focus' status, and that clicking it again clears the focus. 我相信自定义控件正在获得某种“焦点”状态,再次单击它可以清除焦点。 This behavior is evident in the green/blue example. 此行为在绿色/蓝色示例中很明显。 Perhaps the control is being 'highlighted' somehow? 也许控件以某种方式被“突出显示”?

I attempted to implement the solutions given in How can I make a div unselectable? 我试图实施如何使div无法选择?中给出的解决方案 to no effect. 没有任何作用。 I also tried a variety of ways to make the div undraggable in the code, but this did not appear to have any impact. 我还尝试了多种方法来使div在代码中不可拖动,但这似乎没有任何影响。

I also tried simulating mouse clicks on other parts of the program, and double clicking on the control, to change the focus/highlight status, but it appears the API doesn't actually carry out the clicks, only generates events from them. 我还尝试了在程序的其他部分上模拟鼠标单击,然后双击控件以更改焦点/突出显示状态,但是API似乎并未真正执行单击,仅从中生成事件。 I couldn't find a way to cause a 'real' click. 我找不到导致“真正”点击的方法。 Manually clicking, then clicking and dragging worked. 手动单击,然后单击并拖动即可工作。

I also tried making the control draggable but it still has the 'no drag' mouse pointer even when dragging it about. 我也尝试过使控件可拖动,但是即使拖动它,它仍然具有“ no drag”鼠标指针。

If I understand correctly what you are saying, you want to be able to drag a marker onto the map, from outside, and place a point on that position. 如果我正确理解您的意思,则希望能够从外部将标记拖到地图上,然后在该位置上放置一个点。

I have the following solution which does that. 我有以下解决方案。

First we need to build the map: 首先,我们需要构建地图:

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

We create a standard map and add features such as infoWindows to display the lat lng when the marker is added. 我们创建一个标准地图,并添加诸如infoWindows之类的功能以在添加标记时显示经纬度。

In addition we get where the marker is held and onMouseDown call a function (soon to come). 另外,我们获得标记所在的位置,并且onMouseDown调用一个函数(很快就会出现)。

We use b[0] as we are getting the first set of <div> tags in the mark-up below, this is where the draggable icon is held: 我们使用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>

The DummyOView is a map OverlayView which allows us to drag onto the map and grab the coords and position. DummyOView是地图OverlayView,它使我们能够拖到地图上并获取坐标和位置。 More information on SO + credit to : More info 有关SO +信用的更多信息更多信息

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

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

The initDrag function is where most of the work is done, this is quite a lengthy function so I did comment the code, any questions on clarification just add a comment. 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
}

Summarised this function is called whenever the mouse has been clicked and dragged. 总结一下,每当单击并拖动鼠标时都会调用此函数。 It registed the starting position and the positions of the map div and checks when the onmouseup to see if the current mouse position is over the map div. 它注册了开始位置和地图div的位置,并检查onmouseup何时查看当前鼠标位置是否在地图div上。 If so we create a marker on the map and re-add the marker icon to the div to allow redragging. 如果是这样,我们将在地图上创建一个标记,然后将标记图标重新添加到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())
  })
}

Re-adding the marker to the div 将标记重新添加到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 you can use : https://jsfiddle.net/q3wjrpdw/7/ 可以使用JSfiddle: https ://jsfiddle.net/q3wjrpdw/7/

Any questions feel free to ask. 有任何问题请随时询问我(们)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM