我想使用Javascript API创建Google地图自定义控件。
该控件是一个“添加航点”按钮。用户应该能够从控件拖动,导致标记出现在鼠标指针上,并将此标记放在地图上。
预期的行为几乎与现有的街头小人物相同。
问题是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
在这种情况下,当文本突出显示时,您会看到“无拖动”图标。父控件似乎不可选,这是期望的目标。
我相信自定义控件正在获取某种“焦点”状态,再次单击它会清除焦点。这种行为在绿色/蓝色示例中很明显。也许控制是以某种方式“突出”的?
我试图实现How can I make a div unselectable?中给出的解决方案无效。我还尝试了各种方法使代码中的div不可分割,但这似乎没有任何影响。
我还尝试在程序的其他部分模拟鼠标点击,并双击控件,更改焦点/突出显示状态,但似乎API实际上不执行点击,只生成来自他们的事件。我找不到引起'真正'点击的方法。手动单击,然后单击并拖动工作。
我也尝试使控件可拖动,但即使拖动它也仍然有“无拖动”鼠标指针。
答案 0 :(得分: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 +积分的更多信息:More info
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上。如果是这样,我们在地图上创建一个标记,并将标记图标重新添加到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/
任何问题随时可以提出。