Leaflet: map wird bei map.remove() nicht komplett aus dem DOM entfernt

Erstellt am 13. Sept. 2017  ·  37Kommentare  ·  Quelle: Leaflet/Leaflet

So reproduzieren Sie

  • Broschürenversion, die ich verwende: 1.2.0
  • Browser (mit Version) Ich verwende: Chrome Version 60.0.3112.113
  • Es funktioniert gut in Firefox und Safari (nicht in IE, Edge getestet)
  • Betriebssystem/Plattform (mit Version) Ich verwende: macOS Sierra
  • Karte im div-Element hinzufügen und Ebene hinzufügen
this.leafletMap = new L.Map( <element> , {
            zoomControl: true, 
            dragging: this.isInDragMode, 
            touchZoom: false,
            scrollWheelZoom: false,
            doubleClickZoom: false,
            tap: false,
}
L.tileLayer( 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                } ).addTo( this.leafletMap );
  • Entfernen Sie die Karte bei einer Benutzeraktion
if (this.leafletMap ){
        this.leafletMap.eachLayer(function(layer){
            layer.remove();
        });
        this.leafletMap.remove();
        this.leafletMap = null;
    }

Welches Verhalten erwarte ich und welches Verhalten sehe ich

  • Nach dem Entfernen der Karte wird die Karte aus dem Element entfernt. Wenn ich jedoch auf das Div doppelklicke, wird der Fehler ausgegeben - Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined
    Es scheint, als ob das DOM-Element immer noch die Ereignis-Listener enthält, obwohl die Karte und die Layer entfernt wurden.

Minimalbeispiel, das das Problem reproduziert

  • [ ] dieses Beispiel ist so einfach wie möglich
  • [ ] Dieses Beispiel basiert nicht auf Code von Drittanbietern

Verwenden von http://playground-leaflet.rhcloud.com/ oder einer anderen jsfiddle-ähnlichen Site.

needs more info

Hilfreichster Kommentar

@spydmobile hier geht, das habe ich in leicht modifizierter Form gemacht:
Ich habe keine Ahnung, wie man Code in diesem verdammten Kommentarfeld richtig postet, tut mir leid.
Ich habe meinen eigenen Kommentar jetzt ungefähr 10 Mal bearbeitet lol

function removeMap()
{
    var leafletCtrl = get_your_own_leaflet_reference_from_somewhere(), 
    dom = leafletCtrl.getReferenceToContainerDomSomehow(); 

    //This removes most of the events
    leafletCtrl.off();

//After this, the dom element should be good to reuse, unfortunatly it is not
    leafletCtrl.remove(); 

    var removeDanglingEvents = function(inputObj, checkPrefix)
    {
        if(inputObj !== null)
        {
            //Taken from the leaflet sourcecode directly, you can search for these constants and see how those events are attached, why they are never fully removed i don't know
            var msPointer = L.Browser.msPointer,
            POINTER_DOWN =   msPointer ? 'MSPointerDown'   : 'pointerdown',
            POINTER_MOVE =   msPointer ? 'MSPointerMove'   : 'pointermove',
            POINTER_UP =     msPointer ? 'MSPointerUp'     : 'pointerup',
            POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';

            for(var prop in inputObj)
            {
                var prefixOk = checkPrefix ? prop.indexOf('_leaflet_') !== -1 : true, propVal; //if we are in the _leaflet_events state kill everything, else only stuff that contains the string '_leaflet_'
                if(inputObj.hasOwnProperty(prop) && prefixOk)
                {
                    //Map the names of the props to the events that were really attached => touchstart equals POINTER_DOWN etc
                    var evt = []; 
                    if(prop.indexOf('touchstart') !== -1) //indexOf because the prop names are really weird 'touchstarttouchstart36' etc
                    {
                        evt = [POINTER_DOWN];
                    }
                    else if(prop.indexOf('touchmove') !== -1)
                    {
                        evt = [POINTER_MOVE];
                    }
                    else if(prop.indexOf('touchend') !== -1)
                    {
                        evt = [POINTER_UP, POINTER_CANCEL];
                    }

                    propVal = inputObj[prop];
                    if(evt.length > 0 && typeof propVal === 'function')
                    {
                        evt.each(function(domEvent)
                        {
                            dom.removeEventListener(domEvent, propVal, false);
                        });                    
                    }

                    //Reference B-GONE, Garbage b collected.
                    inputObj[prop] = null;
                    delete inputObj[prop];
                }
            }
        }        
    };

    removeDanglingEvents(dom._leaflet_events, false);
    removeDanglingEvents(dom, true);
}

Alle 37 Kommentare

Hallo und vielen Dank, dass Sie sich die Zeit genommen haben, diesen Fehler zu melden.

Es scheint jedoch, dass in den von Ihnen beschriebenen Schritten zum Reproduzieren des Problems etwas fehlt. Ich habe ein Spielplatzbeispiel so gut wie möglich gemäß den obigen Schritten eingerichtet: http://playground-leaflet.rhcloud.com/rezop/edit?html ,output

In diesem Beispiel kann ich keine Fehler sehen, nachdem die Karte entfernt wurde. Offensichtlich passiert also noch etwas, das das von Ihnen angezeigte Problem verursacht. Könnten Sie bitte genauere Angaben machen, damit wir dies aufspüren können.

@perliedman Danke für die schnelle Antwort und das Zusammenstellen des Spielplatzbeispiels. Daran kann ich nicht reproduzieren. Versuche noch ein paar Szenarien. während ich es noch untersuche, ein paar fragen -

Brauche ich eine explizite Layer-Entfernung, wenn ich map.remove() mache? Ich vermute, dass es auch die Entfernung der Schichten übernimmt, aber können Sie das bestätigen?

Und der Grund, warum Sie map.remove() unter timeout haben, ist, dass Sie im Beispiel die Karte direkt nach der Erstellung zerstören, andernfalls muss sie nicht in ein Timeout eingeschlossen werden. Korrekt?

Denken Sie daran, wenn Sie mit Open Source arbeiten, _benutzen__ Sie die Quelle! :wink: Um deine erste Frage zu beantworten, _ja_, remove entfernt die Ebenen: https://github.com/Leaflet/Leaflet/blob/master/src/map/Map.js#L731

Der Grund, warum ich es in ein Timeout eingefügt habe, war, mein Beispiel etwas realistischer zu gestalten, um sicherzustellen, dass die Kachelebene mit geladenen Kacheln tatsächlich richtig initialisiert wurde usw. Das Beispiel funktioniert genauso gut, ohne den remove Aufruf einzufügen ein Timeout, aber es scheint ein bisschen wie ein künstlicher Test zu sein.

Hallo zusammen - ich glaube, ich habe dieses Problem auch. Hier ist mein grundlegender Anwendungsfall:

Ich baue eine Viewer-Komponente (mit dem Leaflet-IIIF- Plugin, aber ich glaube nicht, dass dies hier Auswirkungen hat) für Objekte mit mehreren Seiten / Oberflächen, im Gegensatz zur Anzeige einer tatsächlichen Karte. Wenn der Viewer geladen wird, gibt es eine Reihe von Miniaturansichten, auf die der Benutzer klicken kann, um zu aktualisieren, welche Ansicht eines Objekts im zentralen Bereich der Benutzeroberfläche angezeigt wird.

Wenn der Benutzer die Ansicht ändert, rufe ich map.remove() bevor ich eine neue Karte für die neue Ansicht einrichte. Die neue Karte wird auf demselben DOM-Element wie das alte erstellt (ein div mit einer ID), und ich ändere das DOM in keiner Weise außerhalb von Leaflet.

Auf der ersten Ansicht funktioniert alles einwandfrei. Aber nachdem map.remove() aufgerufen und eine neue Ansicht angezeigt wurde, beschwert sich die Konsole: Cannot read property '_leaflet_pos' of undefined jedes Mal, wenn die Karte gezogen oder gezoomt wird.

Ich kann irgendwann versuchen, ein Minimalbeispiel zu posten, aber das scheint das gleiche Problem zu sein. Dieser Fehler tritt in Chrome auf, aber nicht in Firefox.

@egardner ja, bitte versuchen Sie ein Beispiel zu erstellen, das dies reproduziert!

@egardner genau das gleiche Problem bei einer zuvor stabilen Elektron (Chrom + Node) App, zu der ich zurückkehren musste:
"Broschüre": "1.0.0",
"prospekt.markercluster": "1.0.0-rc.1.0"
von 1.2.0, um den Fehler zu beheben Kann die Eigenschaft '_leaflet_pos' von undefined nicht lesen
Dies war auch nach einem map.remove() der Fall, bevor die Karte im selben DOM-Element neu erstellt wurde. Ich habe gerade keine Zeit, kurzfristig zu erstellen und zu Beispiel zu sein

Wir haben auch ein ähnliches Problem beim Versuch, eine Karte zu zerstören. Sie scheint an Referenzen festzuhalten

Ich wiederhole, was ich oben gesagt habe: Damit wir dieses Problem beheben können, geben Sie bitte ein Beispiel an, das das Problem reproduziert.

Hi. Ich habe diesen Fehler in einer Geige reproduziert. Einfach ausgedrückt, wenn Sie eine Karte innerhalb eines div-Elements erstellen, dann die Methode remove verwenden und die Karte dann auf demselben Div neu auffüllen, wird jede Kartenverschiebung dann einen Fehler generieren
Uncaught TypeError: Eigenschaft '_leaflet_pos' von undefined kann nicht gelesen werden.

Um zu reproduzieren, öffnen Sie meine Geige, klicken Sie auf Karte entfernen, klicken Sie auf Karte platzieren, öffnen Sie dann die Konsole und verschieben Sie die Karte.
http://jsfiddle.net/spydmobile/5hmadjnk/

Beachten Sie, dass es nur in Chorme passiert, nicht in FF

Ja, spydmobile, danke für das Beispiel. Dies ist der gleiche Fehler, den ich in Chrome sehe, wie ich oben gemeldet habe

Ich sehe den gleichen Fehler, aber in einem etwas anderen Anwendungsfall. Der gleiche Fehler wird bei der Größenänderung aufgrund eines invalidateSize Aufrufs ausgegeben:

Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined
    at getPosition (leaflet-src.js:2765)
    at NewClass._getMapPanePos (leaflet-src.js:4378)
    at NewClass._rawPanBy (leaflet-src.js:4180)
    at NewClass.invalidateSize (leaflet-src.js:3509)
    at NewClass.<anonymous> (leaflet-src.js:4244)

Der vollständige Aufrufstapel beginnt beim _onResize Handler. Ich verwende react-leaflet aber kein Teil des Stack-Trace weist darauf hin, oder der lokale Code ist das Problem. Ich habe ein paar ältere Versionen ausprobiert (zB 1.0.3 und 1.2.0 ), weil ich dachte, wir könnten es zumindest auf eine bestimmte 1.x.x Version beschränken, aber ich hatte kein Glück.

Gibt es dazu ein Update? Habe das gleiche Problem hier bei der Integration der Broschüre in meine Bewerbung. Nachdem die Karte zerstört wurde, hat das dom-Element immer noch eine _leaflet_events-Eigenschaft, aber das Entfernen dieses Objekts hat auch nicht geholfen.

Es scheint, dass der Kontext der Handlerfunktion veraltet ist (die private Eigenschaft _mapPane in den Handlerargumenten zeigt auf ein nicht vorhandenes Element).

Das erlebe ich auch. Dies ist eine der ausgelösten Ausnahmen, die ich sehe:

https://sentry.io/share/issue/b414c58ea85c44ee9e0e40ad0781883a/

Es scheint, dass dies meistens passiert, wenn ein Benutzer die Zurück-Schaltfläche des Browsers verwendet, um die Karte zu verlassen.

Ich glaube ich habe die Lösung gefunden:

Das Map-Container-Div enthält noch einige Ereignisse, die auch nach map.off und map.remove ausgelöst werden.

In meinem Fall hat die Karte Eigenschaften, die mit _leaflet_ und einige dieser Funktionen befinden sich auf der Karte selbst in der Eigenschaft "map._leaflet_events".

Diese scheinen als pointerdown , pointermove und dergleichen angehängt zu sein, aber die Namen der Eigenschaften sind wie map._leaflet_touchstarttouchstart32 usw.

Ich habe festgestellt, dass ich das Div für eine andere Karte wiederverwenden kann, wenn ich diese iteriere und manuell entferne (mit removeEventListener dann die Eigenschaft selbst auf Null setze und lösche).
Dies beendete auch die Speicherlecks, die ich sah.

Ich kann hier keinen Code posten, aber wenn Sie die Broschürenquelle nach POINTER_DOWN durchsuchen, sehen Sie die angehängten Ereignisse und wissen, wie man sie trennt.

Ich kann dies in Chrome reproduzieren, aber auch in FF (sowohl in meinem eigenen Projekt als auch mit der von @spydmobile bereitgestellten jsfiddle)

@FLoibl Vielleicht ein Kern, eine Geige oder ein Ausschnitt, der an anderer Stelle gepostet wurde, um die Technik zu demonstrieren, die Sie erfolgreich zur Problemumgehung verwenden?

@spydmobile hier geht, das habe ich in leicht modifizierter Form gemacht:
Ich habe keine Ahnung, wie man Code in diesem verdammten Kommentarfeld richtig postet, tut mir leid.
Ich habe meinen eigenen Kommentar jetzt ungefähr 10 Mal bearbeitet lol

function removeMap()
{
    var leafletCtrl = get_your_own_leaflet_reference_from_somewhere(), 
    dom = leafletCtrl.getReferenceToContainerDomSomehow(); 

    //This removes most of the events
    leafletCtrl.off();

//After this, the dom element should be good to reuse, unfortunatly it is not
    leafletCtrl.remove(); 

    var removeDanglingEvents = function(inputObj, checkPrefix)
    {
        if(inputObj !== null)
        {
            //Taken from the leaflet sourcecode directly, you can search for these constants and see how those events are attached, why they are never fully removed i don't know
            var msPointer = L.Browser.msPointer,
            POINTER_DOWN =   msPointer ? 'MSPointerDown'   : 'pointerdown',
            POINTER_MOVE =   msPointer ? 'MSPointerMove'   : 'pointermove',
            POINTER_UP =     msPointer ? 'MSPointerUp'     : 'pointerup',
            POINTER_CANCEL = msPointer ? 'MSPointerCancel' : 'pointercancel';

            for(var prop in inputObj)
            {
                var prefixOk = checkPrefix ? prop.indexOf('_leaflet_') !== -1 : true, propVal; //if we are in the _leaflet_events state kill everything, else only stuff that contains the string '_leaflet_'
                if(inputObj.hasOwnProperty(prop) && prefixOk)
                {
                    //Map the names of the props to the events that were really attached => touchstart equals POINTER_DOWN etc
                    var evt = []; 
                    if(prop.indexOf('touchstart') !== -1) //indexOf because the prop names are really weird 'touchstarttouchstart36' etc
                    {
                        evt = [POINTER_DOWN];
                    }
                    else if(prop.indexOf('touchmove') !== -1)
                    {
                        evt = [POINTER_MOVE];
                    }
                    else if(prop.indexOf('touchend') !== -1)
                    {
                        evt = [POINTER_UP, POINTER_CANCEL];
                    }

                    propVal = inputObj[prop];
                    if(evt.length > 0 && typeof propVal === 'function')
                    {
                        evt.each(function(domEvent)
                        {
                            dom.removeEventListener(domEvent, propVal, false);
                        });                    
                    }

                    //Reference B-GONE, Garbage b collected.
                    inputObj[prop] = null;
                    delete inputObj[prop];
                }
            }
        }        
    };

    removeDanglingEvents(dom._leaflet_events, false);
    removeDanglingEvents(dom, true);
}

Ah dreifache Backticks, verstanden, ty.

@FLoibl Dies ist eine sehr gute Untersuchung :+1:

Könnten Sie bitte etwas Protokollierung hinzufügen... ? https://github.com/Leaflet/Leaflet/blob/5161140e952969c5da27751b79154a2c93f53bfa/src/dom/DomEvent.Pointer.js#L39 und https://github.com/Leaflet/Leaflet/blob/fe9e0f2333888e8c02f937ds91006b/Event. js#L133

Diese sollten für jedes Event laufen, wenn ein L.Map zerstört wird, und sollten dasselbe tun wie Sie, aber ich frage mich, warum es nicht wie erwartet funktioniert.

Ja, ich kenne diese Funktion und sehe, dass sie aufgerufen wird, aber nicht für alle Ereignisse.

Ich denke, das Problem ist, dass der Code sie als "pointermove" usw. an das dom anhängt, aber die Eigenschaftsnamen sind "touchstart" usw. Auch das Wort "touchstart" wird zweimal im Eigenschaftsnamen angezeigt, möglicherweise ein unerwarteter Doppelkonkat der ID und Eventname?

Sollten diese "Zeiger"-Ereignisse auch unter Windows 10 ohne Touchscreen und in Chrome angehängt werden?
Leider weiß ich nicht genug über das Innenleben von Flugblättern, um eine echte Lösung zu bieten :-(

Ich kenne diese Funktion und sehe, dass sie aufgerufen wird, aber nicht für alle Ereignisse.

Nun stellt sich die Frage: Was sind die Ereignisse, für die removePointerListener nicht aufgerufen wird? Vielleicht fehlt hier oder da ein Funktionsaufruf.

Sollten diese "Zeiger"-Ereignisse auch unter Windows 10 ohne Touchscreen und in Chrome angehängt werden?

Jawohl. Es ist fast unmöglich zu erkennen, ob ein System über einen Touchscreen verfügt. Wenn der Browser also Zeigerereignisse unterstützt, wird davon ausgegangen, dass diese verwendet werden.

Ich weiß nicht genug über das Innenleben von Flugblättern, um eine echte Lösung zu bieten :-(

Hey, verzweifeln Sie nicht, das ist großartige Ermittlungsarbeit! :Lächeln:

Dieser Fehler ist in Version 1.0.3 nicht vorhanden. Ich habe @spydmobile http://jsfiddle.net/5hmadjnk/47/ . Mit Version 1.1.0 ist es bereits da.

@benru89 Dieser Fehler war tatsächlich in 1.0.3 in Form von https://github.com/Leaflet/Leaflet/issues/5263 vorhanden (hauptsächlich behoben durch https://github.com/Leaflet/Leaflet/pull/ 5265).

Die Änderung von 1.0.3 auf 1.1.0 betraf auch das jetzt veraltete L.Mixin.Events und den rollupJS-Build, daher denke ich nicht, dass dies gut nachverfolgt werden kann, nicht einmal mit git bisect .

@IvanSanchez Ich habe die Entfernungsfunktion in 1.0.3 und 1.1.0 verglichen und dies wurde hinzugefügt:

for (i in this._panes) {
    remove(this._panes[i]);
}
this._layers = [];
this._panes = [];
delete this._mapPane;
delete this._renderer;

Wenn ich die 6. Zeile entferne, die das MapPane löscht, verschwindet der Fehler. Ich weiß jedoch nicht, wie sich das Entfernen auswirkt, ich denke, das MapPane muss gelöscht werden, aber dieser Fehler wurde sicherlich eingeführt, als diese Zeile hinzugefügt wurde.

@benru89 Wow, das ist auch eine gute Info :+1:

Ich sehe jedoch gerade nicht, welche Pointer-Event-Handler in Kartenfenstern vorhanden sind :thinking:

Ich denke, indem Sie das Kartenfenster nicht entfernen, maskieren Sie nur das Problem. Als ich die Aufrufliste verfolgte, bestand das Problem darin, dass ein _mapPane-Objekt auf ein zerstörtes dom-Element zeigte und so versuchte, eine zwischengespeicherte Position von undefined zu erhalten. Wenn der Bereich nicht zerstört wird, werden die Geisterereignisse möglicherweise durchlaufen, ohne die Ausnahme auszulösen.

@Floibl Ich stimme Ihnen zu, ich denke, es ist nicht die Lösung, aber ich habe beim Überprüfen der Aufrufliste das null _mapPane bemerkt, deshalb habe ich versucht, diese Zeile nicht zu entfernen. Die Lösung muss darin bestehen, die Ereignishandler richtig zu entfernen, denke ich.

Ich denke, dass der Ereignishandler, der dies verursacht (zumindest in meinem Fall und @spydmobile ), "touchExtend" heißt, also ein Handler für leaflet.draw ist. Ich habe herausgefunden, dass das Entfernen des Imports für leaflet.draw auch die Ausnahmen beendet.

Ich habe einen anderen Workaround gefunden. Das Initialisieren Ihrer Map mit der undokumentierten Option touchExtend : false deaktiviert den problematischen Handler, also keine Ausnahmen mehr. Ich weiß nicht wirklich, welche Funktionen ich dadurch verliere, aber wenn ich mir den Code anschaue, könnten es einige erweiterte Gesten für Handys oder Touchscreens sein? Auf jeden Fall scheint in meiner App alles gut zu funktionieren.

@IvanSanchez Ich bin mir nicht sicher, ob es das gleiche Problem ist, aber es könnte damit zusammenhängen.
Wenn Sie die Karte bei laufender Zoom-Animation zerstören, erhalten Sie denselben Fehler: Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined .

Ich habe versucht, in den Code zu schauen und fand heraus, dass es in Map._animateZoom() eine Zeile gibt: setTimeout(Util.bind(this._onZoomTransitionEnd, this), 250);
Wenn ich es richtig verstanden habe, wird dieser Timeout beim Entfernen der Karte nicht zerstört, daher wird immer die Funktion Map._onZoomTransitionEnd aufgerufen. Es kann sein, dass _"hier oder da ein Funktionsaufruf fehlt"_.

Und der vereinfachte Anrufbaum this._onZoomTransitionEnd -> this._move -> this._getNewPixelOrigin -> this._getMapPanePos -> getPosition(this._mapPane) -> return el._leaflet_pos schlägt fehl, weil this._mapPane _undefined_ ist.

Vielleicht könnte dieser Fall behoben werden, wenn Sie die Aufrufe this._move und this._moveEnd in die Bedingung if (this._mapPane) {} einschließen, aber ich habe nicht getestet, ob dies andere Konsequenzen hat.

Ersetzen Sie dies:

_onZoomTransitionEnd: function () {
    if (!this._animatingZoom) { return; }

    if (this._mapPane) {
        removeClass(this._mapPane, 'leaflet-zoom-anim');
    }

    this._animatingZoom = false;

    this._move(this._animateToCenter, this._animateToZoom);

    // This anim frame should prevent an obscure iOS webkit tile loading race condition.
    requestAnimFrame(function () {
        this._moveEnd(true);
    }, this);
}

mit diesem:

_onZoomTransitionEnd: function () {
    if (!this._animatingZoom) { return; }

    this._animatingZoom = false;

    if (this._mapPane) {
        removeClass(this._mapPane, 'leaflet-zoom-anim');
        this._move(this._animateToCenter, this._animateToZoom);

        // This anim frame should prevent an obscure iOS webkit tile loading race condition.
        requestAnimFrame(function () {
            this._moveEnd(true);
        }, this);
    }
}

Irgendwelche Updates dazu? Ich habe das gleiche Problem. touchExtend : false hilft nicht. Das Problem tritt auf, wenn ich von der Ansicht weg navigiere, in der ich die Karte habe (sie wird an dieser Stelle durch Aufrufen von map.remove() zerstört) und dann zu dieser Ansicht zurück navigiere. Es sollte die neue Karte erstellen und initialisieren, aber ich erhalte den Fehler '_leaflet_pos' bei getPosition in der Methode setMaxBounds :

Uncaught (in promise) TypeError: Cannot read property '_leaflet_pos' of undefined
    at getPosition (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:2445)
    at NewClass._getMapPanePos (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4409)
    at NewClass._moved (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4413)
    at NewClass.getCenter (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3774)
    at NewClass.panInsideBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3488)
    at NewClass._panInsideMaxBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:4220)
    at NewClass.setMaxBounds (webpack-internal:///./node_modules/leaflet/dist/leaflet-src.js:3444)

Und auch in der Methode setView :

Uncaught (in promise) TypeError: Cannot read property '_leaflet_pos' of undefined at getPosition (leaflet-src.js?9eb7:2445) at NewClass._getMapPanePos (leaflet-src.js?9eb7:4409) at NewClass.containerPointToLayerPoint (leaflet-src.js?9eb7:3989) at NewClass._getCenterLayerPoint (leaflet-src.js?9eb7:4446) at NewClass._getCenterOffset (leaflet-src.js?9eb7:4451) at NewClass._tryAnimatedPan (leaflet-src.js?9eb7:4526) at NewClass.setView (leaflet-src.js?9eb7:3181)

Gleiches Problem nach map.remove(), reinitiere meine Karte und erhalte genau diesen Fehler

Gleiches Problem mit v1.6.0. Es ist ein kompliziertes Thema

Hier ist ein SSCCE: https://jsfiddle.net/0oafw694/1/

Grundsätzlich den folgenden Code ausführen …

map = L.map('map');
map.setView(...);
map.setMaxBounds(...);
map.remove();

… lässt zwei Ereignis-Listener angehängt:

moveend: (1) […]
0: Object { fn: _panInsideMaxBounds(), ctx: undefined } // from setMaxBounds

unload: (2) […]
0: Object { fn: _destroy() , ctx: {…} }
1: Object { fn: _destroyAnimProxy(), ctx: undefined }

zoomanim: (1) […]
0: Object { fn: _createAnimProxy(), ctx: undefined }

Ich schätze, zoomanim/_createAnimProxy wird über unload/_destroyAnimProxy abgewickelt, und somit kein Problem. Aber das moveend/_panInsideMaxBounds muss abgemeldet werden. Ich erstelle eine PR…

Ich habe gerade ein Div für die Karte mit einer dynamischen ID erstellt. Wenn ich das Div wiederverwenden muss, entferne ich die vorhandene Karte (), um Speicher freizugeben (obwohl es noch einige Ereignisse gibt) und dann Zeichnen Sie das div mit einer anderen ID neu, damit ich eine neue Karte darin erstelle.

Ich speichere auch alle meine Maps in einem Objekt, damit ich sie entsprechend ihrer ID bearbeiten kann (ich habe manchmal mehr als eine Map sichtbar, alle mit dynamischen IDs).

Gemäß meinen Experimenten mit dem Flugblatt ändern alle Ereignisse (z. B. moveend, movestart usw.), die von Entwicklern manipuliert werden, ihr Standardverhalten und bleiben im Speicher, während das Flugblatt aus dem Dom entladen wird.
Ich hatte dies getan: @moveend="()=>{enableRecenter = true}" und so blieb der Handler von 'moveend' beim Entladen/Entfernen der Karte im Speicher.
Ich habe die Manipulationen (meine eigenen Implementierungen) dieser Methoden aus der Kartenkomponente selbst entfernt und dieser Fehler wird jetzt nicht mehr angezeigt.

BERÜHREN SIE NIEMALS DIE KARTENMETHODEN !!! Natürlich, es sei denn, die Bibliothek erkennt dieses Verhalten und behebt diesen Fehler.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen