Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
242 views
in Technique[技术] by (71.8m points)

vue.js - convert leaflet marker extension to Typescript

I've found a leaflet extension that hides map markers if they are outside of the current view map bounds.

import L from 'leaflet';

L.Marker.MyMarker= L.Marker.extend({}).addInitHook(function (this: ILazyMarker) {
    this.on(
        'add',
        function (this: ILazyMarker) {
            this._updateIconVisibility = function (this: ILazyMarker) {
                var map = this._map,
                    isVisible = map.getBounds().contains(this.getLatLng()),
                    wasVisible = this._wasVisible,
                    icon = this._icon,
                    iconParent = this._iconParent,
                    shadow = this._shadow,
                    shadowParent = this._shadowParent;

                // remember parent of icon
                if (!iconParent) {
                    iconParent = this._iconParent = icon.parentNode;
                }
                if (shadow && !shadowParent) {
                    shadowParent = this._shadowParent = shadow.parentNode;
                }

                // add/remove from DOM on change
                if (iconParent != null && isVisible != wasVisible) {
                    if (isVisible) {
                        iconParent.appendChild(icon);
                        if (shadowParent != null && shadow) {
                            shadowParent.appendChild(shadow);
                        }
                    } else {
                        iconParent.removeChild(icon);
                        if (shadowParent != null && shadow) {
                            shadowParent.removeChild(shadow);
                        }
                    }

                    this._wasVisible = isVisible;
                }
            };

            // on map size change, remove/add icon from/to DOM
            this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
            this._updateIconVisibility();
        },
        this,
    );
});

This works fine, but I'd rather use a Typescript class for consistency within my project. Here's my attempt to convert this:

import L from 'leaflet';

export default class MyMarker extends L.Marker {
    _wasVisible!: boolean;
    _icon!: any;
    _shadowParent!: any;
    _iconParent!: any;

    constructor(latlng: L.LatLngExpression, options?: L.MarkerOptions) {
        super(latlng, options);
    }

    onAdd(): this {
        this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
        this._updateIconVisibility();
        return this;
    }

    _updateIconVisibility() {
        var map = this._map,
            isVisible = map.getBounds().contains(this.getLatLng()),
            wasVisible = this._wasVisible,
            icon = this._icon,
            iconParent = this._iconParent,
            shadow = this._shadow,
            shadowParent = this._shadowParent;

        // remember parent of icon
        if (!iconParent) {
            iconParent = this._iconParent = icon.parentNode;
        }
        if (shadow && !shadowParent) {
            shadowParent = this._shadowParent = shadow.parentNode;
        }

        // add/remove from DOM on change
        if (iconParent != null && isVisible != wasVisible) {
            if (isVisible) {
                iconParent.appendChild(icon);
                if (shadowParent != null && shadow) {
                    shadowParent.appendChild(shadow);
                }
            } else {
                iconParent.removeChild(icon);
                if (shadowParent != null && shadow) {
                    shadowParent.removeChild(shadow);
                }
            }

            this._wasVisible = isVisible;
        }
    }
}

When I try to use the class-based marker, I get this error for each marker I am adding and the map will not render:

TypeError: Cannot read property 'parentNode' of undefined
    at MyMarker._updateIconVisibility (leaflet-my-marker.ts:78)
    at MyMarker.onAdd (leaflet-my-marker.ts:63)
    at MyMarker._layerAdd (leaflet-src.js:6567)
    at NewClass.whenReady (leaflet-src.js:4428)
    at NewClass.addLayer (leaflet-src.js:6629)
    at NewClass.addLayer (leaflet-src.js:6780)
    at VueComponent.addLayer (LLayerGroup.js:164)
    at VueComponent.FirecamMarker.mounted (MyMarker.vue?6277:99)
    at invokeWithErrorHandling (vue.runtime.esm.js:1854)
    at callHook (vue.runtime.esm.js:4219)
question from:https://stackoverflow.com/questions/65852126/convert-leaflet-marker-extension-to-typescript

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Proposed "Law of StackOverflow": No matter how long you've worked on a piece of code, you will not be able to solve the problem until you post it on StackOverflow

I've worked on this off and on for several days... of course, I am able to solve it immediately after posting my question. I needed to call the super's onAdd method within my onAdd method, like so:

onAdd(): this {
    super.onAdd(this._map);
    this._map.on('resize moveend zoomend', this._updateIconVisibility, this);
    this._updateIconVisibility();
    return this;
}

This makes sense because the original code calls to .addInitHook() not .setInitHook().


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...