Leaflet: Kartenkacheln werden erst geladen, wenn ein Zoom ausgeführt wird

Erstellt am 6. Nov. 2014  ·  61Kommentare  ·  Quelle: Leaflet/Leaflet

Nach dem Update auf Leaflet 0.8-dev werden meine Kacheln nicht reibungslos geladen. In der anfänglichen Karte fehlt eine Kachel, die angezeigt wird. Wenn ich mit dem Ebenensteuerelement zu anderen Kachelebenen wechsle, wird eine vollständig leere Karte angezeigt. Keine Fehler in der Konsole. Wenn ich jedoch zoome, werden die Kacheln aktualisiert und alle geladen. Siehe beigefügte Screenshots.
screenshot at nov 06 14-40-53
screenshot at nov 06 14-41-18

bug projections

Hilfreichster Kommentar

Hallo, ich habe mir den Testfall angesehen und konnte den Code auf diesen Wert reduzieren:

var mapCrs = L.extend({}, L.CRS.EPSG4326, {
        scale: function(zoom) {
            return 512 * Math.pow(2, zoom);
        },
        wrapLat: false,
        wrapLng: false
    }),
    map = new L.map('map', {
        center: [0, 0],
        zoom: 0,
        crs: mapCrs
    });

L.tileLayer('http://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}', {
    attribution: false,
    continuousWorld: true,
    tileSize: 512
}).addTo(map);

map.setView([0, 0], 0, {
    reset: true
});

Das Entfernen von reset: true aus dem Aufruf von setView behebt das Problem und zeigt die Karte korrekt an. Ich habe noch nicht genauer nachgesehen, aber da es sich um ein ziemlich einfaches Beispiel handelt, ähnelt es den Abstürzen, die wir zuvor mit setView hatten.

Ich bin offensichtlich zu dumm, um herauszufinden, wie man plunkr benutzt, also habe ich es aufgegeben, eine Abzweigung des ursprünglichen Codes zu machen. Ich denke, Sie können den obigen Code einfach in den ursprünglichen plunkr kopieren.

@ rwwagner90 Ich denke, Sie wissen bereits, dass das Ändern von CRS nach der Initialisierung der Karte, wie in Ihrem Beispiel, derzeit nicht offiziell unterstützt wird.

Alle 61 Kommentare

Können Sie einen Link zu einer JSFiddle- oder Beispielseite erstellen?

Ich kann den Fehler derzeit nicht reproduzieren. Ich arbeite an einem Plunker, aber er scheint gut zu laden, also nicht sicher, was mir fehlt. Ich kann keinen Link zu meinem eigentlichen Code teilen, glaube ich nicht. Ich hatte gehofft, jemand hätte ein ähnliches Problem gesehen und weiß, wie man es löst. Ich werde weiter daran arbeiten, es zu reproduzieren, aber wir haben eine Menge Code, den ich reproduzieren muss.

Ok, Sie können es gerne wieder öffnen, wenn Sie einen reproduzierbaren Testfall haben.

Ich habe mir die Kacheln noch einmal angesehen, die zurückgeschickt werden, und es scheint, dass für die, die ich nicht sehe, keine Anfrage gesendet wurde. Wenn ich dann heraus- und wieder hineinzoome, werden alle Kacheln korrekt angefordert. Ich weiß, dass es einen großen TileLayer-Refactor gab. Gibt es also eine Chance, dass jemand weiß, warum ein oder zwei Anfragen zunächst fehlen und dann nach dem Zoomen funktionieren?

Keine Ahnung. Wir brauchen einen Testfall, um das herauszufinden.

Gibt es eine Möglichkeit, die Kacheln einfach manuell neu zu laden oder so? Ich kann keinen Testfall erstellen, wir haben viel zu viel in unserem Code.

Ich konnte tatsächlich einen Testfall machen. Hier ist es: http://plnkr.co/edit/ny5hAUNVvnA5uNGPMRyg?p=preview

Beachten Sie, dass beim Laden nur die Hälfte der Karte geladen wird. Wenn Sie ein paar Mal hinein- und herauszoomen, wird der Rest geladen.

Außerdem sehe ich im Änderungsprotokoll: removed the need for TileLayer hacks when using custom projections.

Worauf bezieht sich das? Wir erweitern 4326, um den richtigen Maßstab und die richtige Transformation zu erreichen. Ist das nicht mehr nötig?

Hat sich jemand den von mir bereitgestellten Testfall angesehen? Ich würde mich sehr über Hilfe freuen!

@perliedman einige seltsame Projektionen Zeug

Nur dieses und ein oder zwei weitere Probleme, und wir sollten mit Leaflet 0.8-dev arbeiten. Mir ist klar, dass wir vielleicht eine Reihe ungewöhnlicher Anforderungen haben, aber ich schätze wirklich alles, was Sie alle getan haben, um zu helfen! Es wäre großartig, wenn wir in den nächsten Tagen die Ursache dieser verbleibenden Probleme ermitteln könnten. Bitte lassen Sie mich wissen, was ich tun kann, um zu helfen.

Hat jemand eine Idee, warum diese Kacheln nicht geladen werden? Ist @perliedman der Verantwortliche für Projektionen?

Hallo, ich habe mir den Testfall angesehen und konnte den Code auf diesen Wert reduzieren:

var mapCrs = L.extend({}, L.CRS.EPSG4326, {
        scale: function(zoom) {
            return 512 * Math.pow(2, zoom);
        },
        wrapLat: false,
        wrapLng: false
    }),
    map = new L.map('map', {
        center: [0, 0],
        zoom: 0,
        crs: mapCrs
    });

L.tileLayer('http://services.arcgisonline.com/arcgis/rest/services/ESRI_Imagery_World_2D/MapServer/tile/{z}/{y}/{x}', {
    attribution: false,
    continuousWorld: true,
    tileSize: 512
}).addTo(map);

map.setView([0, 0], 0, {
    reset: true
});

Das Entfernen von reset: true aus dem Aufruf von setView behebt das Problem und zeigt die Karte korrekt an. Ich habe noch nicht genauer nachgesehen, aber da es sich um ein ziemlich einfaches Beispiel handelt, ähnelt es den Abstürzen, die wir zuvor mit setView hatten.

Ich bin offensichtlich zu dumm, um herauszufinden, wie man plunkr benutzt, also habe ich es aufgegeben, eine Abzweigung des ursprünglichen Codes zu machen. Ich denke, Sie können den obigen Code einfach in den ursprünglichen plunkr kopieren.

@ rwwagner90 Ich denke, Sie wissen bereits, dass das Ändern von CRS nach der Initialisierung der Karte, wie in Ihrem Beispiel, derzeit nicht offiziell unterstützt wird.

@mourner Ich bin nicht vertraut genug mit der Funktionsweise von GridLayer und TileLayer, um sicherzugehen, ob dies ein Problem ist, aber es sieht für mich so aus, als ob Folgendes passiert:

  • Durch das Zurücksetzen der Ansicht wird TileLayer._abortLoading aufgerufen und die Kachel src s auf emptyImageUrl
  • Wenn _addTiles später aufgerufen wird, befinden sich die Kacheln immer noch im Cache _tiles und werden nicht zur Ladewarteschlange hinzugefügt

Sollten die Kacheln nicht aus dem _tiles Cache entfernt werden, wenn sie abgebrochen werden?

Wenn reset: true nicht verwendet wird, wird das Laden der Kacheln nie abgebrochen, was das Problem vermutlich löst.

@perliedman ha, nette Untersuchung! Ja, es ist wahrscheinlich eine Rennbedingung, bei der der _tiles Cache nicht rechtzeitig gelöscht wird - er soll später gelöscht werden, aber _addTiles beginnt vorher.

@perliedman Sie zerstören also nur die gesamte Karte und erstellen eine neue, um dies zu

Ist dieser Rennzustand leicht zu beheben?

Ja, wahrscheinlich leicht zu reparieren. Werde es mir morgen ansehen.

@ rwwagner90 eigentlich nicht sicher, was ich empfehlen würde, wollte Sie nur warnen, dass Leaflet nicht für AFAIK entwickelt wurde, und Sie könnten in Verrücktheit geraten. Auf der anderen Seite scheint es, wie Sie gezeigt haben, möglich zu sein, mit etwas Geigen zu arbeiten.

Wenn Leaflet dies in der API unterstützen würde, sollte es meiner Meinung nach eine setCrs -Methode oder ähnliches geben, um diese technischen Details zu verbergen und es Plugins zu ermöglichen, auf CRS-Änderungen zu reagieren, indem sie ein Ereignis auslösen.

Ich denke auch, wir würden jemanden brauchen, der diese Funktion tatsächlich benötigt, um sie zu verstärken und zu implementieren: wink:

Weitere Diskussionen hierzu sollten in # 2553 veröffentlicht werden.

@mourner Wenn du heute die Rennbedingungen reparieren

@perliedman Sobald alle meine Funktionen funktionieren, habe ich möglicherweise Zeit, eine setCrs-Methode zu implementieren. Ich denke, es wäre eine gute Idee, dies zu unterstützen.

@ rwwagner90 Ich werde sehen, was ich gegen die Rennbedingungen tun kann.

Eine dynamische Änderung des CRS ist für Leaflet in Kürze nicht geplant. Wenn dies viele komplexe Änderungen und zusätzlichen Code für den Leaflet-Kern bedeutet, werde ich wahrscheinlich auch keine Pull-Anfrage akzeptieren.

@mourner Vielen Dank!

Was CRS betrifft, sollte es im Grunde genommen so ziemlich die Methode sein, die ich verwendet habe. Vielleicht könnten wir die Dinge nur leicht optimieren und diese Problemumgehung anbieten. Auf diese Weise würde es unterstützt, aber wir müssten keine wesentlichen Änderungen an der Leaflet-Codebasis vornehmen.

@ Trauernder Glück mit der Rennbedingung? Ich würde es wirklich begrüßen, wenn es repariert würde!

@mourner @perliedman Wenn mich jemand darauf hinweisen könnte, wo die Rennbedingungen sind, könnte ich einen Blick darauf werfen. Dies ist eines von nur zwei verbleibenden Problemen, bei denen ich auf Leaflet 0.8-dev umsteige.

@ rwwagner90 ziemlich genau beschrieben in https://github.com/Leaflet/Leaflet/issues/3002#issuecomment -62960089, können Sie nach Methodennamen im Quellcode suchen.

@mourner Ich habe gerade hinzugefügt:

this._tiles = {};

_AddTiles löscht jetzt nur noch die Kacheln, bevor weitere hinzugefügt werden. Dies scheint zu funktionieren, aber ich gehe davon aus, dass der Zweck, den Kachel-Cache zu haben, zunichte gemacht wird.

BEARBEITEN:
Eigentlich mag es sinnvoller sein, es am Ende von _abortLoading hinzuzufügen, aber wahrscheinlich ist es immer noch nicht das, was wir wollen.

_abortLoading: function () {
        var i, tile;
        for (i in this._tiles) {
            tile = this._tiles[i];

            tile.onload = L.Util.falseFn;
            tile.onerror = L.Util.falseFn;

            if (!tile.complete) {
                tile.src = L.Util.emptyImageUrl;
                L.DomUtil.remove(tile);
            }
        }
        this._tiles = {};
    }

Ja, das ist falsch. Stattdessen müssen Sie Kacheln löschen, die in _abortLoading abgebrochen wurden.

@mourner Okay, ich versuche nur diejenigen zu entfernen, die jetzt nicht vollständig waren. Das habe ich getan:

_abortLoading: function () {
        var i, tile;
        for (i in this._tiles) {
            tile = this._tiles[i];

            tile.onload = L.Util.falseFn;
            tile.onerror = L.Util.falseFn;

            if (!tile.complete) {
                tile.src = L.Util.emptyImageUrl;
                L.DomUtil.remove(tile);
                delete this._tiles[i];
            }

        }
    }

Ist das die richtige Lösung?

Funktioniert es für dich?

Es funktioniert beim ersten Laden der Karte, aber wenn ich gehe und zurückkomme, funktioniert es nicht. Wenn ich es aus dem if(!tile.complete) herausschiebe, funktioniert es die ganze Zeit, aber ich nehme an, ich entleere im Wesentlichen nur den Cache wieder, oder?

_abortLoading: function () {
        var i, tile;
        for (i in this._tiles) {
            tile = this._tiles[i];

            tile.onload = L.Util.falseFn;
            tile.onerror = L.Util.falseFn;

            if (!tile.complete) {
                tile.src = L.Util.emptyImageUrl;
                L.DomUtil.remove(tile);
            }
            delete this._tiles[i];
        }
    }

Ich glaube, die Lösung innerhalb von if(!tile.complete) ist die richtige oder nahe daran, aber es hat nicht in allen Fällen für mich funktioniert, also habe ich den Hack damit nur außerhalb des if in meinem Code gehalten zur Zeit. Was denkst du

@mourner Ich denke, vielleicht ist die Lösung in der if-Anweisung die richtigste, und dann könnte das Problem, später auf die Seite zurückzukehren und bei mir nicht zu funktionieren, getrennt sein. Was denkst du? Dies ist eine halbe Lösung:

_abortLoading: function () {
        var i, tile;
        for (i in this._tiles) {
            tile = this._tiles[i];

            tile.onload = L.Util.falseFn;
            tile.onerror = L.Util.falseFn;

            if (!tile.complete) {
                tile.src = L.Util.emptyImageUrl;
                L.DomUtil.remove(tile);
                delete this._tiles[i];
            }

        }
    }

Beachten Sie, dass mit dieser Änderung das plnkr jetzt funktioniert: http://plnkr.co/edit/ny5hAUNVvnA5uNGPMRyg?p=preview

Eigentlich scheint das plnkr immer noch nicht zu funktionieren. Ich konnte sehen, dass es gelegentlich funktioniert, aber wenn Sie die Seite aktualisieren, ist sie immer noch defekt.

Gibt es eine Möglichkeit, das zu unterstützen, was wir versuchen, ohne Reset zu verwenden: true und ohne jedes Mal eine brandneue Karte zu erstellen, oder ist dies die einzige Möglichkeit, CRS im laufenden Betrieb zu wechseln?

@ rwwagner90 Ich denke die Antwort ist, dass niemand wirklich weiß. Sie scheinen einer der wenigen zu sein, die CRS wechseln, und da es nicht unterstützt / empfohlen wird, glaube ich nicht, dass es von sehr vielen getestet wurde.

@ rwwagner90 kannst du das nochmal mit dem neuesten master überprüfen? Es gab einige Änderungen im Zusammenhang mit dem Laden von Kacheln.

Ich kann versuchen, mein plnkr zu bearbeiten und zu sehen, ob es funktioniert. Ich war im letzten Monat oder so bei einem anderen Projekt, also habe ich mir die Broschüre nicht so genau angesehen.

Dies scheint nichts mit dem CRS zu tun zu haben, ich kann es mit diesem Beispiel reproduzieren:

var map = L.map('map').setView([52, 4], 3);
L.tileLayer('http://c.tile.stamen.com/toner/{z}/{x}/{y}.png').addTo(map);

// these two lines each stop the tiles from loading until the first zoom interaction
map.setView([52.1, 4], 3, {animate: false});
// map.setView([52.1, 4], 3, {reset: true});

http://jsfiddle.net/rord0mak/

Ich erlebe dies auch mit einem normalen setView @jieter. In Ihrer Geige funktioniert es, wenn Sie Ihre setView in ein setTimeout von beispielsweise 1000 ms einwickeln. Es muss also eine Rennbedingung sein, bei der es zu früh ausgelöst wird. Ich erlebe dies jedoch zufällig während des Lebenszyklus der Verwendung meiner App, nicht nur unmittelbar nach dem Laden.

Irgendwelche Updates? Können wir genau bestimmen, wann und warum die Kacheln nicht mehr geladen werden? Ich bekomme eine Kachel zum Laden, dann werden keine zusätzlichen Kacheln mehr benötigt, um den Container zu füllen. Sobald ich die Größe meines Bildschirms verändere, werden alle verbleibenden Kacheln aufgerufen und von da an funktioniert es.

Bearbeiten: Ich verwende Höhe 100%, wenn ich die Höhe des Containers auf eine bestimmte Zahl setze, die gut geladen wird. Die Kacheln werden beim Rendern für die Höhe des Containers geladen, aber der Container hat nicht die wahre Höhe von 100%. Die Ladefunktion erhält nicht die richtige Höhe des Containers.

Ich mache ein bisschen Hackery, um meine Karte auf 100% Höhe @bmulcahy zu zwingen. Vielleicht bringt das 100% große Zeug es irgendwie durcheinander? Meins ist sehr gehackt, um dieses Problem zu beheben.

Ich denke es ist das @ rwwagner90 .

Ich habe dies nach dem Laden meiner Seite zu meinem Code hinzugefügt
app.map.refresh (0);

app.map.refresh = function(timeout){
      window.setTimeout(function(){
      app.map.invalidateSize();
},timeout);
    };

Ich habe das Zeitlimit hinzugefügt, weil ich in meiner App ein zusammenklappbares Bedienfeld habe, das die invalidateSize nach Abschluss der Animation (0,5 s) nicht auslöst. Es wird sofort nach dem Start ausgelöst, sodass ich den grauen Bereich in meiner habe Kartencontainer.

Durch Hinzufügen von invalidateSize wird die Broschüre gezwungen, die wahre Größe des Containers zu überprüfen.

Wir sollten jedoch keine Hacks einführen müssen, damit das Laden der Kacheln abgeschlossen ist. Hier gibt es immer noch einen Fehler.

@ rwwagner90 stimmte zu, dass ich nur eine vorübergehende Lösung lieferte.

Wahrscheinlich ohne Bezug, aber ich hatte ein Problem, bei dem, wenn ich marker.openPopup() und dann sofort map.fitBounds() anrief, die Kacheln nicht mehr geladen wurden und ich eine leere schwarze Karte bekam.

Geben Sie dies hier ein, falls es für andere Personen gilt, die über eine zufällige Google-Suche auf dieses Problem stoßen.

Ich habe auch dieses Problem, aber die Karte hat in einem Div gut funktioniert, bis ich das Div in mein Formular verschoben habe. Nicht alle Kacheln werden geladen, aber wenn ich die Größe des Browsers ändere, werden sie alle gut geladen. Der Zoom für mich lädt die Kacheln nicht neu. Meine Höhe war bei einem festen px, versuchte die Breite bei 100% und bei festem, änderte sich aber nicht, es fehlten immer noch Kacheln. Unter Verwendung von Faltblatt 0.7.3 wird immer noch, wenn dies in 0.8-dev gelöst ist, dorthin verschoben.

@patriciaorgan ruft nach der Manipulation des Containers map.invalidateSize() und es sollte in Ordnung sein.

Ich bin auch auf dieses Problem mit 1.0 Beta 1 gestoßen. Map hat einwandfrei funktioniert, bis ich habe . Die Karte zoomt korrekt auf den Ort, aber die Kacheln werden erst geladen, wenn ich schwenke oder verkleinere.

map.locate({
  setView: true
});

Bearbeiten: Es gab bereits ein anderes Problem für dieses https://github.com/Leaflet/Leaflet/issues/3659

Ich habe eine neue Version von @ rwwagner90s plunkr erstellt, die die neueste Entwicklungsversion von Leaflet verwendet: https://playground-leaflet.rhcloud.com/jis/edit?html , Ausgabe

Es scheint, dass das Problem behoben wurde, da alle Kacheln ohne Probleme geladen werden. Das Überprüfen von @jieters jsfiddle (http://jsfiddle.net/rord0mak/) scheint dasselbe anzuzeigen.

Ich schließe dies als behoben, kann aber weitere Informationen hinzufügen, wenn das Problem weiterhin besteht.

Dies ist wahrscheinlich ein wenig albern, aber ich hatte dieses Problem und dann wurde mir klar, dass ich JS ausführte, bevor ich CSS lud.
Aus irgendeinem Grund tritt dieses Problem nicht mehr auf, wenn ich ihre Positionen tausche (dh zuerst CSS und dann JS lade).

Keine Ahnung, ob jemand anderes ein ähnliches Problem hatte, aber es hat dieses Problem für mich behoben.

@mourner Bei Verwendung von Faltblatt 1.0.3 ist dieser Fehler ziemlich häufig

@michaeltrim hast du einen Testfall, der das Problem reproduziert? Überprüfen Sie auch # 5622 und # 5381, um festzustellen, ob sie auf Sie zutreffen.

@perliedman Es ist in einer großen Client-Codebasis so nicht einfach, da das Problem sowieso so zeitweise auftritt. Es sieht so aus, als könnte es durchaus mit diesen beiden Problemen zusammenhängen. Meine App läuft in Elektronen und lädt Kacheln aus dem Dateisystem. Ist das in 1.1.0 behoben?

@michaeltrim # 5381 wurde in 1.1.0 behoben, führte jedoch ein weiteres Problem (# 5622) ein, das wir in der kommenden Version beheben.

Ich habe festgestellt, dass das gleiche Problem mit dem Compiler less-js auftritt.
Der Compiler wurde entfernt, das Problem ist behoben.

github
Ich habe das gleiche Problem mit meiner React-Faltblatt-App.

Ein sehr ähnliches Problem mit "leaflet": "^1.3.4" mit "vuetify": "^1.2.0" Keine Lösung gefunden.
screen shot 2018-10-13 at 8 48 13 pm

@humblecoder höchstwahrscheinlich haben Sie vergessen, leaflet.css-Stile zu importieren

@cherniavskii Du https://unpkg.com/[email protected]/dist/leaflet.css aber es hat nicht funktioniert. Ich wechselte zu http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css und es funktionierte. 🤷‍♂️

aber es hat nicht funktioniert

Was meinst du damit? Dieser Link funktioniert bei mir.

Ich habe zu http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css gewechselt und es hat funktioniert.

Beachten Sie, dass dies Stile für Faltblatt v0.7.7 sind. Sie sollten dieselbe Version der .js- und .css-Leaflet-Dateien verwenden

@cherniavskii Richtig, der Link 0.7.7 funktioniert. Die, die ich zuvor verwendet habe ( 1.3.4 ), hat dies nicht getan. Zu Ihrer Information, ich bin einfach require ('leaflet') in VueJS und importiere das JS nicht von CDN.

Beide arbeiten für mich.

Übrigens können Sie CSS auch aus node_modules importieren

Ja, habe das auch getan 😆. . . Import von leaflet/dist/leaflet.css . Jetzt ist alles gut. Vielen Dank.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

viswaug picture viswaug  ·  4Kommentare

gdbd picture gdbd  ·  3Kommentare

edmsgists picture edmsgists  ·  3Kommentare

prbaron picture prbaron  ·  3Kommentare

timwis picture timwis  ·  3Kommentare