Cum se desenează linii drepte în interiorul poligonului de pe harta Google (Programare, Javascript, Google Maps, Google Maps Api 3, Poligon)

Sandeep a intrebat.

Am creat o hartă Google folosind google map javascript API V3. Desenez un număr de poligoane de coduri poștale. Poligoanele sunt de culori diferite în funcție de anumite condiții. Acum vreau să desenez linii drepte/marci hașurate în interiorul unora dintre poligoane în funcție de anumite criterii. Cum se poate face acest lucru. Mai jos este codul pe care l-am scris pentru desenarea poligoanelor.

{% if zip.zip_info.zip_polygon %}
    var path = [
        {% for polycoord in zip.zip_info.zip_polygon %}
            new google.maps.LatLng({{polycoord.1}}, {{polycoord.0}}),
        {% endfor %}
        ];

    var polygon_{{ forloop.counter }} = new google.maps.Polygon(
    {
        path:path, 
        clickable:true,
        strokeColor: '#000000',
        strokeOpacity: 0.15,
        strokeWeight: 2,
        fillColor: fillColor,
        fillOpacity: 1,
        zipcode: '{{zip.zip_info.zipcode}}'
    });

    polygon_{{ forloop.counter }}.setMap(map);

{% endif %}

De asemenea, dau și linkul imaginii cu cerința mea.

Puteți vedea în imagine că o parte din poligoane sunt umbrite cu linii drepte, iar altele sunt umbrite doar cu culori.

Comentarii

  • Se pare că doriți o „textură” de umplere, ca aceasta cerere de îmbunătățire –  > Por geocodezip.
  • Da vreau să adaug o textură, altfel spus putem spune că vreau să desenez linii în interiorul poligonului. putem face asta. –  > Por sandeep.
  • Nu puteți face acest lucru cu API-ul în acest moment. Puteți vota pentru această cerere de îmbunătățire (sau găsiți o alta mai bună pentru scopul dvs. sau creați una nouă). S-ar putea să puteți face ceva cu Polylines, dar probabil că va avea un impact asupra performanței. –  > Por geocodezip.
  • Mulțumesc geocodezip. Dar unde pot posta cererea de îmbunătățire a API-ului sau unde pot vota. Vă rugăm să mă ghidați. –  > Por sandeep.
  • Linkul din primul meu comentariu. (code.google.com/p/gmaps-api-issues/issues/detail?id=598) –  > Por geocodezip.
3 răspunsuri
Bryan Weaver

Am lucrat la aceeași problemă. Aceasta este ceea ce am până acum: jsFiddle de exemplu

The BW.PolyLineFill creează un fișier suprapunere personalizată. Aceasta acceptă 4 parametri, ultimii doi fiind opționali.

 1. path: an array of Google LatLng objects   
 2. map: the map to attach theoverlay to 
 3. fillColor: (optional) the color of the fill, default is red. 
 4. strokeColor: (optional) the stroke color, default is black

Nu am testat performanța și probabil că mai are nevoie de câteva modificări, dar ar trebui să vă ajute să începeți.

Codul relevant:

PolyLineFill.prototype = new google.maps.OverlayView();
function PolyLineFill(poly, map, fill, stroke) {
    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.div_ = null;
    this.poly_ = poly;
    this.polysvg_ = null;
    this.fill_ = fill;
    this.stroke_ = stroke;

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

PolyLineFill.prototype.onAdd = function () {
    // Create the DIV and set some basic attributes.
    var div = document.createElement('div');
    div.style.borderStyle = 'none';
    div.style.borderWidth = '0px';
    div.style.position = 'absolute';

    //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");
    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 polygon to the div
    var p = document.createElementNS(svgns, "polygon");
    p.setAttributeNS(null, "fill", "url(#lineFill)");
    p.setAttributeNS(null, "stroke", "#000");
    p.setAttributeNS(null, "stroke-width", "1");
    //set a reference to this element;
    this.polysvg_ = p;
    svg.appendChild(p);

    div.appendChild(svg);

    // Set the overlay's div_ property to this DIV
    this.div_ = div;

    // 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.overlayLayer.appendChild(div);
}

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.div_;
    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.polysvg_.setAttributeNS(null, "points", this.AdjustPoints());
}

PolyLineFill.prototype.onRemove = function () {
    this.div_.parentNode.removeChild(this.div_);
    this.div_ = null;
}
window.BW = {};
window.BW.PolyLineFill = PolyLineFill;

Comentarii

  • Vreun alt progres în acest sens? Se pare că funcționează, dar de îndată ce faceți zoom, lucrurile nu mai arată corect. –  > Por BigDubb.
  • @BigDubb ați putea fi mai specific cu privire la ceea ce nu funcționează? Exemplul de suprapunere din exemplul de vioară de mai sus nu se aliniază exact cu limitele definite pe harta Google, deoarece am luat rapid niște Geodata pe care să le folosesc pentru exemplu. Este posibil ca proiecțiile hărții să fie puțin diferite între cea folosită pentru a colecta datele și proiecțiile Google. Date mai precise ar avea rezultate mai bune sau cel puțin date în concordanță cu proiecția aleasă de Google. Cred că Google folosește o proiecție Mercator, așa că, dacă folosiți un alt tip, veți obține o ușoară deplasare la transpunerea în coordonate pe ecran. –  > Por Bryan Weaver.
  • Am pornit acest lucru în Chrome. Măresc în Utah și, odată ce am trecut de un anumit nivel de zoom, nu mai desenează corect poligonul. Părți din el nu se redau, iar dacă măresc suficient de mult, dispare cu totul. –  > Por BigDubb.
  • Am implementat soluția dvs. în aplicația mea și am aceeași problemă pe care a văzut-o @BigDubb. Voi verifica codul pentru a vedea dacă o pot rezolva, dacă nu cumva aveți deja un patch pentru a o rezolva. –  > Por christiansr85.
  • Am rezolvat comportamentul ciudat atunci când se făcea zoom pe hartă (se poate observa că svg era tăiat). Am adăugat o clasă css pentru a da 100% la înălțimea și lățimea acesteia. Acum problema cu zoom-ul este rezolvată. Pe de altă parte am schimbat tipul formei redate. Am desenat un path în loc de un polygon pentru că în testele mele, în cazul în care path elementul răspundea mai bine la evenimentele mouse-ului, cum ar fi mouse over, mouse click… Link către exemplul meu –  > Por christiansr85.
Heitor Marcos

Am lucrat la soluția lui Bryan Weaver pentru a o face să funcționeze pentru poligoane editabile folosind managerul de desen. iată exemplul jsfiddle

Berry Ratliff

Se poate face în CANVAS:

http://home.provide.net/~bratliff/hawaii/

Faceți clic pe alegerile radio „stil” pentru a vedea alte modele opționale.

Comentarii

  • Da, am văzut exemplul din link, care funcționează. Dar putem să o facem folosind google map V3 API js. –  > Por Sandeep.
  • Acest lucru funcționează numai pe imagini statice, probabil de ce folosesc hărțile statice Google. –  > Por Dennis.