Избегайте наложения на карты Google Maps

Я создал пример скрипта здесь, где любой может проверить мою проблему.

Эта проблема заключается в том, что когда два наложения (построенные с элементом svg и path внутри него) расположены слишком близко, т. Е. Бок о бок, и обе формы имеют неправильные пределы, тогда последняя визуализированная форма перекрывает первую.

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

Область, в которой нижний оверлей не доступен для нажатия

Существует css правило смены курсора, когда он находится над path. Вы также можете видеть, что в указанной области курсор не меняется.

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


person christiansr85    schedule 23.01.2015    source источник
comment
Это проблема с полифилом.   -  person geocodezip    schedule 23.01.2015
comment
Я читал кое-что о полифилле, и я думаю, что это может быть проблема с полифилом, но есть ли в настоящее время какое-либо решение этой проблемы в частности?   -  person christiansr85    schedule 26.01.2015


Ответы (1)


Наконец, я попытался найти другое решение, например, поместить все элементы под позицию мыши и определить, какой path находился в тот момент под указателем, и выполнить действие над ним. Я искал способ реализовать это решение и нашел это сообщение: решение! !, где есть как раз то, что мне нужно.

Я думаю, что это лучший и более элегантный способ (по крайней мере, лучше, чем я думал раньше) решить мою проблему. По сути, он добавляет правило css pointer-events: none; к верхнему svg элементу, который блокирует другие 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>

person christiansr85    schedule 27.01.2015