避免谷歌地图覆盖物重叠问题

3

我已经创建了一个这里的示例,任何人都可以检查我的问题。

问题是当两个覆盖层(使用svg元素和内部path构建)过于接近,即并排,并且两个形状都具有不规则的限制时,最后呈现的形状会重叠在第一个形状上。

在视觉上,您无法欣赏它,但如果您为path dom元素添加例如单击事件以显示其名称,则最后呈现的形状在其整个区域内是可点击的,但第一个形状并非完全可点击。下图中标记的区域对于下面的图片而言是不可点击的,但实际上应该是可点击的:

Region where the bottom overlay is not clickable

当鼠标悬停在路径上时,有一个CSS规则可以改变光标。您还可以看到,在指定区域内,光标不会改变。

如何避免这种重叠?我想要的是使底部形状完全可点击。


这是一个 polyfill 的问题。 - geocodezip
我读到了关于polyfill的一些内容,我认为这可能是一个polyfill问题,但是,现在有没有特别针对这个问题的解决方案? - christiansr85
1个回答

2

最后,我试图找到另一种解决方案,比如获取鼠标位置下的所有元素,并确定那时在指针下方的path,并在其上执行操作。我正在寻找一种实现这个解决方案的方法,然后我发现了这个帖子:解决方案!,其中正是我所需要的。

我认为这是解决我的问题的最佳和更加优雅的方式(至少比我之前想象的要好)。基本上,它在顶部svg元素上添加了CSS规则pointer-events: none;,该元素阻止其他path元素。对于path对象,我已经添加了pointer-events: all;。因此,CSS样式应如下所示:

svg.overlay {
   pointer-events: none;
}

svg.overlay > path {
   pointer-events: all;
}    

整个解决方案(您也可以在jsfiddler示例中看到):

 function initialize() {
   var myLatLng = new google.maps.LatLng(42, -111.02783203125);
   var mapOptions = {
     zoom: 6,
     center: myLatLng,
     mapTypeId: google.maps.MapTypeId.ROADMAP
   };

   var map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

   //polygon coords for Utah
   var path = [
     new google.maps.LatLng(41.983994270935625, -111.02783203125),
     new google.maps.LatLng(42.00032514831621, -114.01611328125),
     new google.maps.LatLng(36.96744946416931, -114.01611328125),
     new google.maps.LatLng(37.00255267215955, -109.0283203125),
     new google.maps.LatLng(40.97989806962013, -109.0283203125),
     new google.maps.LatLng(41.0130657870063, -111.02783203125)
   ];

   // custom overlay created
   var overlay = new BW.PolyLineFill(path, map, 'red', '#000', 'original');

   // polygon coords for conflict shape
   var pathConflict = [
     new google.maps.LatLng(42.00032514831621, -114.01611328125),
     new google.maps.LatLng(41.983994270935625, -111.02783203125),
     new google.maps.LatLng(41.0130657870063, -111.02783203125),
     new google.maps.LatLng(40.97989806962013, -109.0283203125),
     new google.maps.LatLng(47.00255267215955, -109.0283203125),
     new google.maps.LatLng(46.96744946416931, -114.01611328125)
   ];


   var overlayConflict = new BW.PolyLineFill(pathConflict, map, 'white', '#000', 'conflict');

 }

 ///Start custom poly fill code
 PolyLineFill.prototype = new google.maps.OverlayView();

 function PolyLineFill(poly, map, fill, stroke, name) {
   var bounds = new google.maps.LatLngBounds();
   for (var i = 0; i < poly.length; i++) {
     bounds.extend(poly[i]);
   }

   //initialize all properties.
   this.bounds_ = bounds;
   this.map_ = map;
   this.$dom = null;
   this.poly_ = poly;
   this.polysvg_ = null;
   this.fill_ = fill;
   this.stroke_ = stroke;

   this.name_ = name;

   // Explicitly call setMap on this overlay
   this.setMap(map);
 }

 PolyLineFill.prototype.onAdd = function() {

   //createthe svg element
   var svgns = "http://www.w3.org/2000/svg";
   var svg = document.createElementNS(svgns, "svg");
   svg.setAttributeNS(null, "preserveAspectRatio", "xMidYMid meet");

   var def = document.createElementNS(svgns, "defs");

   //create the pattern fill 
   var pattern = document.createElementNS(svgns, "pattern");
   pattern.setAttributeNS(null, "id", "lineFill-" + this.name_);
   pattern.setAttributeNS(null, "patternUnits", "userSpaceOnUse");
   pattern.setAttributeNS(null, "patternTransform", "rotate(-45)");
   pattern.setAttributeNS(null, "height", "7");
   pattern.setAttributeNS(null, "width", "7");
   def.appendChild(pattern);

   var rect = document.createElementNS(svgns, "rect");
   rect.setAttributeNS(null, "id", "rectFill");
   rect.setAttributeNS(null, "fill", this.fill_ || "red");
   rect.setAttributeNS(null, "fill-opacity", "0.3");
   rect.setAttributeNS(null, "stroke", this.stroke_ || "#000");
   rect.setAttributeNS(null, "stroke-dasharray", "7,7");
   rect.setAttributeNS(null, "height", "7");
   rect.setAttributeNS(null, "width", "7");
   pattern.appendChild(rect);

   svg.appendChild(def);

   //add path to the div
   var path = document.createElementNS(svgns, 'path');
   path.setAttributeNS(null, 'fill', 'url(#lineFill-' + this.name_ + ')');
   path.setAttributeNS(null, 'stroke', '#000');
   path.setAttributeNS(null, 'stroke-width', '1');
   path.setAttributeNS(null, 'pointer-events', 'all');
   this.path_ = path;

   svg.appendChild(this.path_);

   svg.style.borderStyle = 'none';
   svg.style.borderWidth = '0px';
   svg.style.position = 'absolute';
   svg.style.pointerEvents = 'none';
   svg.setAttribute('class', 'polygon');

   this.$dom = svg;

   // We add an overlay to a map via one of the map's panes.
   // We'll add this overlay to the overlayLayer pane.
   var panes = this.getPanes();
   panes.overlayMouseTarget.appendChild(this.$dom);

   var dragging = false;

   google.maps.event.addDomListener(this.path_, 'mousedown', function(evt) {
     dragging = false;
   });

   google.maps.event.addDomListener(this.path_, 'mousemove', function(evt) {
     dragging = true;
   });

   var _self = this;
   // onclick listener
   google.maps.event.addDomListener(this.path_, 'click', function(evt) {
     if (dragging) {
       return false;
     }
     alert('clicked on ' + _self.name_);
   });
 }

 PolyLineFill.prototype.AdjustPoints = function() {
   //adjust the polygon points based on the projection.
   var proj = this.getProjection();
   var sw = proj.fromLatLngToDivPixel(this.bounds_.getSouthWest());
   var ne = proj.fromLatLngToDivPixel(this.bounds_.getNorthEast());

   var points = "";
   for (var i = 0; i < this.poly_.length; i++) {
     var point = proj.fromLatLngToDivPixel(this.poly_[i]);
     if (i == 0) {
       points += (point.x - sw.x) + ", " + (point.y - ne.y);
     } else {
       points += " " + (point.x - sw.x) + ", " + (point.y - ne.y);
     }
   }
   return points;
 }

 PolyLineFill.prototype.draw = function() {
   // Size and position the overlay. We use a southwest and northeast
   // position of the overlay to peg it to the correct position and size.
   // We need to retrieve the projection from this overlay to do this.
   var overlayProjection = this.getProjection();

   // Retrieve the southwest and northeast coordinates of this overlay
   // in latlngs and convert them to pixels coordinates.
   // We'll use these coordinates to resize the DIV.
   var sw = overlayProjection.fromLatLngToDivPixel(this.bounds_.getSouthWest());
   var ne = overlayProjection.fromLatLngToDivPixel(this.bounds_.getNorthEast());

   // Resize the image's DIV to fit the indicated dimensions.
   var div = this.$dom;
   div.style.left = sw.x + 'px';
   div.style.top = ne.y + 'px';
   div.style.width = (ne.x - sw.x) + 'px';
   div.style.height = (sw.y - ne.y) + 'px';

   this.path_.setAttributeNS(null, "d", 'M' + this.AdjustPoints() + 'z');
 }

 PolyLineFill.prototype.onRemove = function() {
   this.div_.parentNode.removeChild(this.div_);
   this.div_ = null;
 }
 window.BW = {};
 window.BW.PolyLineFill = PolyLineFill;
 ///end poly fill code


 google.maps.event.addDomListener(window, 'load', initialize);
 html,
 body {
   height: 100%;
   margin: 0;
   padding: 0;
 }
 .polygon: {
   pointer-events: none;
 }
 .polygon > path {
   cursor: pointer;
   pointer-events: all;
 }
 .polygon > path:active {
   cursor: -webkit-grabbing;
 }
 #map-canvas,
 #map_canvas {
   height: 100%;
 }
 @media print {
   html,
   body {
     height: auto;
   }
   #map_canvas {
     height: 650px;
   }
 }
<script src="http://maps.google.com/maps/api/js?sensor=false&.js"></script>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="map-canvas"></div>


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接