Leaflet: لا تتم إزالة الخريطة بالكامل من map.remove () من DOM

تم إنشاؤها على ١٣ سبتمبر ٢٠١٧  ·  37تعليقات  ·  مصدر: Leaflet/Leaflet

كيف تتكاثر

  • إصدار المنشور الذي أستخدمه: 1.2.0
  • المتصفح (مع الإصدار) الذي أستخدمه: إصدار Chrome 60.0.3112.113
  • يعمل بشكل جيد في Firefox و Safari (لم يتم اختباره في IE و Edge)
  • نظام التشغيل / النظام الأساسي (مع الإصدار) الذي أستخدمه: macOS Sierra
  • أضف خريطة في عنصر div وأضف طبقة
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 );
  • إزالة الخريطة على بعض إجراءات المستخدم
if (this.leafletMap ){
        this.leafletMap.eachLayer(function(layer){
            layer.remove();
        });
        this.leafletMap.remove();
        this.leafletMap = null;
    }

ما هو السلوك الذي أتوقعه وأي سلوك أراه

  • بعد إزالة الخريطة ، فإنه يزيل الخريطة من العنصر ، ومع ذلك ، إذا قمت بالنقر نقرًا مزدوجًا على div ، فسيظهر خطأ - Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined
    يبدو أن عنصر DOM لا يزال يحتفظ بمنصات الأحداث على الرغم من إزالة الخريطة والطبقات.

مثال بسيط على إعادة إنتاج المشكلة

  • [] هذا المثال بسيط قدر الإمكان
  • [] هذا المثال لا يعتمد على أي كود طرف ثالث

استخدام http://playground-leaflet.rhcloud.com/ أو أي موقع آخر يشبه jsfiddle.

needs more info

التعليق الأكثر فائدة

spydmobile هنا يذهب ، هذا ما فعلته بصيغة معدلة قليلاً:
ليس لدي أي فكرة عن كيفية إرسال الرمز بشكل صحيح في حقل التعليق هذا ، آسف لذلك.
لقد قمت بتحرير تعليقي الخاص حوالي 10 مرات الآن لول

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);
}

ال 37 كومينتر

مرحبًا وشكرًا على الوقت الذي قضيته في الإبلاغ عن هذا الخطأ.

ومع ذلك ، يبدو أن هناك شيئًا مفقودًا من الخطوات التي تصفها لإعادة إظهار المشكلة. لقد قمت بإعداد مثال لملعب كما يمكنني القيام به على طول الخطوات أعلاه: http://playground-leaflet.rhcloud.com/rezop/edit؟html ، الإخراج

في هذا المثال ، لا يمكنني رؤية أي أخطاء بعد إزالة الخريطة ، لذلك يبدو أن هناك شيئًا آخر يحدث يسبب المشكلة التي تراها. هل يمكنك تقديم مزيد من التفاصيل ، حتى نتمكن من تعقب ذلك.

perliedman شكرًا للاستجابة السريعة ووضع مثال لملعب. لا أستطيع التكاثر على ذلك. تجربة عدد قليل من السيناريوهات. بينما ما زلت أبحث في الأمر ، بضعة أسئلة -

هل أحتاج إلى إزالة صريحة للطبقة ، إذا كنت أعمل map.remove() ؟ تخميني هو أنه سيهتم بإزالة الطبقة أيضًا ، لكن هل يمكنك التأكيد.

والسبب في وجود map.remove () تحت timeout هو أنك في المثال تقوم بتدمير الخريطة بعد الإنشاء مباشرةً ، وإلا فليس مطلوبًا إرفاقها بمهلة. صيح؟

تذكر ، عند العمل مع المصدر المفتوح ، استخدم المصدر! : wink: للإجابة على سؤالك الأول ، _yes_ ، remove سيزيل الطبقات: https://github.com/Leaflet/Leaflet/blob/master/src/map/Map.js#L731

وكان السبب وضعه في مهلة لجعل بلدي على سبيل المثال قليلا أكثر واقعية، والتأكد من ان طبقة البلاط تهيئة الواقع بشكل صحيح مع البلاط تحميل، وما إلى ذلك المثال يعمل فقط كذلك دون تعريض remove الدعوة في مهلة ، لكنها تبدو وكأنها اختبار مصطنع.

مرحبًا - أعتقد أنني أعاني من هذه المشكلة أيضًا. إليك حالة الاستخدام الأساسية الخاصة بي:

أقوم بإنشاء مكون عارض (باستخدام المكون الإضافي Leaflet-IIIF ، لكنني لا أعتقد أن هذا يؤثر على أي شيء هنا) للكائنات ذات الصفحات / الأسطح المتعددة بدلاً من عرض خريطة فعلية. عند تحميل العارض ، توجد سلسلة من الصور المصغرة التي يمكن للمستخدم النقر عليها لتحديث طريقة عرض الكائن التي يتم عرضها في المنطقة المركزية لواجهة المستخدم.

عندما يغير المستخدم العرض ، أتصل بـ map.remove() قبل إعداد خريطة جديدة للعرض الجديد. تم إنشاء الخريطة الجديدة على نفس عنصر DOM مثل العنصر القديم (div بمعرف) ، وأنا لا أقوم بتعديل DOM بأي شكل من الأشكال خارج Leaflet.

في العرض الأولي كل شيء يعمل بشكل جيد. ولكن بعد استدعاء map.remove() وإظهار طريقة عرض جديدة ، تشكو وحدة التحكم: Cannot read property '_leaflet_pos' of undefined كلما تم سحب الخريطة أو تكبيرها.

يمكنني محاولة نشر مثال بسيط في وقت ما ، ولكن يبدو أن هذه هي نفس المشكلة. يظهر هذا الخطأ في Chrome وليس في Firefox.

egardner نعم ، يرجى محاولة إنشاء مثال يعيد إنتاج هذا!

egardner بالضبط نفس المشكلة على تطبيق الإلكترون المستقر سابقًا (Chromium + Node) الذي اضطررت إلى الرجوع إليه:
"نشرة": "1.0.0"،
"Leaflet.markercluster": "1.0.0-rc.1.0"
من 1.2.0 لإزالة الخطأ لا يمكن قراءة الخاصية '_leaflet_pos' من undefined
كان هذا أيضًا بعد map.remove () قبل إعادة إنشاء الخريطة في نفس عنصر DOM. ليس لدي الوقت الآن فقط للإبداع والمثال على المدى القصير

نحن نواجه أيضًا مشكلة مماثلة في محاولة تدمير خريطة ، يبدو أننا نتمسك بالمراجع

سأكرر ما قلته أعلاه: حتى نتمكن من فعل أي شيء حيال هذه المشكلة ، يرجى تقديم مثال يعيد إنتاج المشكلة.

أهلا. لقد كررت هذا الخطأ في كمان. ببساطة ، إذا قمت بإنشاء خريطة داخل عنصر div ، ثم استخدم طريقة الإزالة ، ثم أعد ملء الخريطة على نفس عنصر div ، ستؤدي كل حركة للخريطة بعد ذلك إلى حدوث خطأ
خطأ في النوع غير معلوم: لا يمكن قراءة الخاصية '_leaflet_pos' من undefined.

لإعادة الإنتاج ، افتح كمانتي ، وانقر على إزالة الخريطة ، وانقر على خريطة المكان ، ثم افتح وحدة التحكم وحرك الخريطة.
http://jsfiddle.net/spydmobile/5hmadjnk/

لاحظ أن هذا يحدث فقط في Chorme ، وليس في FF

نعم ، شكرًا spydmobile على المثال ، هذا هو الخطأ نفسه الذي أراه في Chrome كما ذكرت أعلاه

أرى نفس الخطأ ولكن في حالة استخدام مختلفة قليلاً. تم طرح نفس الخطأ عند تغيير الحجم بسبب مكالمة invalidateSize :

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)

يبدأ مكدس الاستدعاءات الكامل عند معالج _onResize . أنا أستخدم react-leaflet لكن لا يوجد أي جزء من تتبع المكدس يشير إلى ذلك أو أن الرمز المحلي هو المشكلة. لقد جربت عددًا قليلاً من الإصدارات القديمة (مثل 1.0.3 و 1.2.0 ) معتقدًا أننا قد نكون قادرين على الأقل على تأمينه على إصدار 1.x.x ، لكن لم يحالفني الحظ.

هل هناك أي تحديث على ذلك؟ أواجه نفس المشكلة هنا دمج النشرة في طلبي. بعد تدمير الخريطة ، لا يزال عنصر dom يحتوي على خاصية _leaflet_events ، لكن التخلص من هذا الكائن لم يساعد أيضًا.

يبدو أن سياق دالة المعالج لا معنى له (تشير الخاصية الخاصة _mapPane في أرغس المعالج إلى عنصر غير موجود).

أنا أواجه هذا أيضًا. هذا أحد الاستثناءات الملقاة التي أراها:

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

يبدو أن هذا يحدث غالبًا عندما يستخدم المستخدم زر الرجوع في المتصفحات لمغادرة الخريطة.

أعتقد أنني قد وجدت الحل:

لا يزال لدى حاوية الخريطة div بعض الأحداث التي يتم تشغيلها حتى بعد map.off و map.remove .

في حالتي ، تحتوي الخريطة على خصائص تبدأ بـ _leaflet_ وبعض هذه الوظائف وجدت أنها موجودة على الخريطة نفسها في الخاصية "map._leaflet_events".

يبدو أنها مرفقة كـ pointerdown ، pointermove map._leaflet_touchstarttouchstart32 وهكذا لكن أسماء الخصائص مثل

لقد وجدت أنه إذا قمت بتكرار هذه الأشياء وإزالتها يدويًا (باستخدام removeEventListener ثم إلغاء وحذف الخاصية نفسها كمقياس جيد) ، يمكنني إعادة استخدام div لخريطة أخرى.
هذا أيضًا وضع حدًا لتسريبات الذاكرة التي كنت أراها.

لا يمكنني كتابة الكود هنا ، ولكن إذا بحثت في مصدر المنشور عن POINTER_DOWN سترى الأحداث المرفقة ، وتعرف كيفية فصلها.

يمكنني إعادة إنتاج هذا على Chrome ولكن أيضًا في FF (سواء في مشروعي الخاص أو باستخدام jsfiddle المقدم منspydmobile)

FLoibl ربما يتم نشر جوهر أو كمان أو بعض المقتطف في مكان آخر لتوضيح التقنية التي تستخدمها بنجاح

spydmobile هنا يذهب ، هذا ما فعلته بصيغة معدلة قليلاً:
ليس لدي أي فكرة عن كيفية إرسال الرمز بشكل صحيح في حقل التعليق هذا ، آسف لذلك.
لقد قمت بتحرير تعليقي الخاص حوالي 10 مرات الآن لول

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);
}

آه ثلاثية باكتيكس ، فهمت ، تاي.

FLoibl هذا تحقيق جيد جدًا: +1:

هل يمكنك إضافة بعض قطع الأشجار حول ...؟ https://github.com/Leaflet/Leaflet/blob/5161140e952969c5da27751b79154a2c93f53bfa/src/dom/DomEvent.Pointer.js#L39 و https://github.com/Leaflet/Leaflet/blob/fe9e0f2333888e/ شبيبة # L133

يجب أن يتم تشغيلها لكل حدث عندما يتم تدمير L.Map ، ويجب أن تفعل نفس الشيء الذي تفعله ، لكنني أتساءل لماذا لا يعمل كما هو متوقع.

نعم ، أعرف هذه الوظيفة وأرى أنه يتم استدعاؤها ، ولكن ليس لجميع الأحداث.

أعتقد أن المشكلة تكمن في أن الكود يرفقهم كـ "pointermove" وما إلى ذلك إلى dom ، لكن أسماء الخصائص هي "touchstart" وما إلى ذلك أيضًا ، كما تظهر كلمة "touchstart" مرتين في اسم الخاصية ، وربما تكون سلسلة doube غير متوقعة من معرف واسم الحدث؟

هل يجب أيضًا إرفاق أحداث "المؤشر" هذه على نظام التشغيل Windows 10 بدون شاشة تعمل باللمس وفي Chrome؟
للأسف ، لا أعرف ما يكفي عن الأعمال الداخلية للمنشورات لتوفير حل حقيقي :-(

أعرف هذه الوظيفة وأرى أنه يتم استدعاؤها ، ولكن ليس لجميع الأحداث.

السؤال الآن هو: ما هي الأحداث التي لم يتم استدعاء removePointerListener أجلها؟ ربما نفتقد استدعاء دالة هنا أو هناك.

هل يجب أيضًا إرفاق أحداث "المؤشر" هذه على نظام التشغيل Windows 10 بدون شاشة تعمل باللمس وفي Chrome؟

نعم فعلا. يكاد يكون من المستحيل اكتشاف ما إذا كان النظام يحتوي على شاشة تعمل باللمس ، لذلك إذا كان المتصفح يدعم أحداث المؤشر ، فإن الافتراض هو أنه سيتم استخدامها.

لا أعرف ما يكفي عن الأعمال الداخلية للمنشورات لتقديم حل حقيقي :-(

مرحبًا ، لا تيأس ، هذا عمل تحقيق رائع! :ابتسامة:

هذا الخطأ غير موجود في الإصدار 1.0.3. التقطت spydmobile jsfiddle وقمت بتغيير إصدار المنشور واختفى الخطأ http://jsfiddle.net/5hmadjnk/47/ . مع الإصدار 1.1.0 يوجد بالفعل.

@ benru89 كان هذا الخطأ موجودًا في الواقع في 1.0.3 ، في شكل https://github.com/Leaflet/Leaflet/issues/5263 (تم إصلاحه غالبًا بواسطة https://github.com/Leaflet/Leaflet/pull/ 5265).

أثر التغيير من 1.0.3 إلى 1.1.0 أيضًا على L.Mixin.Events الذي تم إهماله الآن وبناء rollupJS ، لذلك لا أعتقد أنه يمكن تتبع ذلك بشكل جيد ، ولا حتى مع git bisect .

IvanSanchez لقد قارنت وظيفة الإزالة في 1.0.3 و 1.1.0 وأضيف هذا:

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

إذا قمت بإزالة السطر السادس ، فسيتم حذف الخط الذي يحذف الخريطة. لا أعرف مع ذلك تأثير إزالة هذا ، أعتقد أنه يجب حذف MapPane ولكن تم تقديم هذا الخطأ بالتأكيد عند إضافة هذا السطر.

@ benru89 واو ، هذه أيضًا معلومات جيدة: +1:

أنا فقط لا أرى معالجات أحداث المؤشر الموجودة في أجزاء الخريطة في الوقت الحالي ، على الرغم من: التفكير:

أعتقد أنه من خلال عدم إزالة جزء الخريطة ، فإنك تخفي المشكلة فقط. عندما تعقبت مكدس الاستدعاءات ، كانت المشكلة أن بعض كائن _mapPane كان يشير إلى عنصر dom مدمر وبالتالي يحاول الحصول على موضع مخبأ من غير معرف. إذا لم يتم إتلاف الجزء ، فقد تمر أحداث الشبح دون تشغيل الاستثناء.

Floibl أتفق معك ، أعتقد أنه ليس هو الحل ، لكنني لاحظت أن null _mapPane عند فحص مكدس المكالمات ، ولهذا السبب حاولت عدم إزالة هذا السطر. يجب أن يكون الحل إلى جانب إزالة معالجات الأحداث بشكل صحيح على ما أعتقد.

أعتقد أن معالج الحدث الذي تسبب في حدوث ذلك (على الأقل في حالتي و spydmobile ) يسمى "touchExtend" لذا فهو معالج رسومات المنشور. اكتشفت أن إزالة الاستيراد للنشرة.رسم يوقف الاستثناءات أيضًا.

لقد وجدت حلاً آخر. يؤدي بدء تشغيل خريطتك باستخدام الخيار غير الموثق touchExtend : false إلغاء تنشيط المعالج الإشكالي ، لذلك لا مزيد من الاستثناءات. لا أعرف حقًا الميزات التي أفقدها من خلال القيام بذلك ولكن بالنظر إلى الكود ، فقد تكون بعض الإيماءات الموسعة للجوال أو الشاشات التي تعمل باللمس ؟؟ على أي حال ، يبدو أن كل شيء في تطبيقي يعمل بشكل جيد.

IvanSanchez لست متأكدًا من أنها نفس المشكلة ، ولكن يمكن أن تكون ذات صلة.
عندما تدمر الخريطة عندما تكون حركة التكبير / التصغير قيد التقدم ، تحصل على الخطأ نفسه: Uncaught TypeError: Cannot read property '_leaflet_pos' of undefined .

حاولت النظر داخل الكود ووجدت أنه يوجد داخل Map._animateZoom() سطر: setTimeout(Util.bind(this._onZoomTransitionEnd, this), 250);
إذا فهمت ذلك بشكل كافٍ ، فلن يتم إتلاف هذه المهلة عند إزالة الخريطة ، لذلك يتم دائمًا استدعاء الوظيفة Map._onZoomTransitionEnd . يمكن أن يكون _ "فقدان استدعاء دالة هنا أو هناك" _.

وشجرة الاتصال المبسطة this._onZoomTransitionEnd -> this._move -> this._getNewPixelOrigin -> this._getMapPanePos -> getPosition(this._mapPane) -> return el._leaflet_pos فشل this._mapPane _undefined_.

ربما يمكن إصلاح هذه الحالة ، إذا قمت بلف المكالمات this._move و this._moveEnd في حالة if (this._mapPane) {} ، لكنني لم أختبر ما إذا كان لها بعض النتائج الأخرى.

استبدل هذا:

_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);
}

مع هذا:

_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);
    }
}

أي تحديثات على هذا؟ أواجه نفس المشكلة. touchExtend : false لا يساعد. تحدث المشكلة عندما أتنقل بعيدًا عن العرض ، حيث لدي الخريطة (يتم تدميرها في هذه المرحلة عن طريق استدعاء map.remove ()) ثم انتقل مرة أخرى إلى طريقة العرض هذه. يجب إنشاء الخريطة الجديدة وتهيئتها ، لكنني أتلقى الخطأ "_leaflet_pos" عند getPosition في طريقة 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)

وأيضًا في طريقة 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)

نفس المشكلة بعد map.remove () ، أعد تعيين خريطتي واحصل على هذا الخطأ بالضبط

نفس المشكلة مع v1.6.0. إنها قضية معقدة

إليك SSCCE: https://jsfiddle.net/0oafw694/1/

في الأساس ، تشغيل الكود التالي ...

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

... يترك اثنين من مستمعي الأحداث مرفقتين:

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 }

أعتقد أنه يتم التعامل مع zoomanim/_createAnimProxy عبر unload/_destroyAnimProxy ، وبالتالي لا توجد مشكلة. لكن moveend/_panInsideMaxBounds يحتاج إلى أن يكون غير مسجّل. سأقوم بإعداد العلاقات العامة ...

لقد انتهيت للتو من إنشاء div للخريطة التي تحتوي على معرف ديناميكي ، لذلك عندما يتعين علي إعادة استخدام div ، أقوم بإزالة () الخريطة الحالية من أجل تحرير الذاكرة (حتى مع استمرار وجود بعض الأحداث) ثم أعد رسم div بمعرف مختلف لذلك أقوم بإنشاء خريطة جديدة فيه.

أقوم أيضًا بتخزين جميع خرائطي في كائن ، حتى أتمكن من معالجتها وفقًا لمعرفها (لدي أكثر من خريطة واحدة مرئية في بعض الأحيان ، وكلها مع معرفات ديناميكية)

وفقًا لتجاربي مع المنشور ، مهما كانت الأحداث (على سبيل المثال ، moveend ، movestart ، إلخ) التي يتم التلاعب بها من قبل المطورين ، فإنها تغير سلوكهم الافتراضي وتبقى في الذاكرة أثناء تفريغ المنشور من dom.
لقد فعلت هذا: @moveend="()=>{enableRecenter = true}" وهكذا ، بقي معالج "moveend" في الذاكرة أثناء تفريغ / إزالة الخريطة.
لقد أزلت عمليات التلاعب (تطبيقاتي الخاصة) لهذه الطرق من مكون الخريطة نفسه والآن توقف هذا الخطأ عن الظهور.

لذلك ، في الأساس ، لا تلمس طرق الخريطة على الإطلاق !!! بالطبع ، ما لم تكتشف المكتبة هذا السلوك وتقوم بإصلاح هذا الخطأ.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات