简体   繁体   English

谷歌地图:如何更新标记

[英]Google Maps: How To Update Markers

I have an observable which emits a list of properties.我有一个可观察的,它发出一个属性列表。 Based on the property latitude longitude I am rendering custom HTML markers using google map overlays.基于属性纬度经度,我正在使用谷歌 map 叠加层呈现自定义 HTML 标记。

First time when the map is loading, markers and clusters are rendering properly.第一次加载 map 时,标记和集群正在正确渲染。 From the second time onwards I am trying to remove previous markers and placing the new ones.从第二次开始,我试图删除以前的标记并放置新的标记。 At this point, old markers are not removed (I have already added a remove method) and new markers getting added.此时,旧标记未被删除(我已经添加了一个删除方法)并添加了新标记。 Also, the cluster is not showing from second time.此外,集群从第二次开始就没有显示。

Question: How to update markers in Google maps?问题:如何更新谷歌地图中的标记?

html-map-marker.ts html-map-marker.ts

export const createHTMLMapMarker = ({
    OverlayView = google.maps.OverlayView,
    ...args
}) => {
    class HTMLMapMarker extends google.maps.OverlayView {
        private label!: string;
        private marker!: HTMLElement | null;
        private latlng!: google.maps.LatLng;

        constructor() {
            super();
            this.latlng = args['latlng'];
            this.label = args['label'];
            this.setMap(args['map']);
        }

        public createDiv() {
            this.marker = document.createElement('div') as HTMLElement;
            this.marker.classList.add('custom-marker-box');

            if (this.label && this.marker !== null) {
                const markerInnerEl = document.createElement('div');
                markerInnerEl.classList.add('custom-marker');
                const markerInnerTextEl = document.createElement('span');
                markerInnerTextEl.innerText = this.label;
                markerInnerEl.appendChild(markerInnerTextEl);
                this.marker.appendChild(markerInnerEl);
                this.marker.style.cssText = `position: absolute; cursor: pointer;`;

                /**
                 * !Stops click or tap on the element from bubbling up to the map.
                 * !Use this to prevent the map from triggering "click" events.
                 */
                google.maps.OverlayView.preventMapHitsFrom(this.marker);
            }

            google.maps.event.addDomListener(
                this.marker,
                'click',
                (event: MouseEvent) => {
                    const targetEl = event.target as HTMLElement;
                    const ClickedMarkerEl =
                        targetEl.tagName.toLocaleLowerCase() === 'span'
                            ? targetEl.parentNode
                            : targetEl;

                    const markers =
                        document.querySelectorAll('.custom-marker-box');

                    markers.forEach((markerParent) => {
                        const markerEl = markerParent
                            .children[0] as HTMLElement;

                        if (markerEl === ClickedMarkerEl) {
                            if (
                                !markerEl.classList.contains(
                                    'custom-marker-active'
                                )
                            ) {
                                markerEl.classList.add('custom-marker-active');
                            }
                        } else {
                            markerEl.classList.remove('custom-marker-active');
                        }
                    });
                    google.maps.event.trigger(this, 'click');
                }
            );
        }

        public appendDivToOverlay() {
            const panes = this.getPanes() as google.maps.MapPanes;
            panes.floatPane.appendChild(this.marker as HTMLElement);
        }

        public positionDiv() {
            const point = this.getProjection().fromLatLngToDivPixel(
                this.latlng
            );
            if (point) {
                const markerWidth = (
                    this.marker as HTMLElement
                ).getBoundingClientRect().width;
                const marginAmount = (markerWidth / 2).toFixed();

                (this.marker as HTMLElement).style.left = `${point.x}px`;
                (this.marker as HTMLElement).style.top = `${point.y}px`;
                (
                    this.marker as HTMLElement
                ).style.marginLeft = `-${marginAmount}px`;
            }
        }

        public override draw() {
            if (!this.marker) {
                this.createDiv();
                this.appendDivToOverlay();
            }
            this.positionDiv();
        }

        public remove() {
            if (this.marker) {
                this.marker.parentNode?.removeChild(this.marker);
                this.marker = null;
            }
        }

        public getPosition() {
            return this.latlng;
        }

        public getDraggable() {
            return false;
        }
    }
    return new HTMLMapMarker();
};

google-map.component.ts google-map.component.ts

    private markers: any[] = [];
    private initialZoom!: boolean;
    private googleMap!: google.maps.Map;
    private properties: IProperty[] = [];
        
    ngOnInit(): void {
       this.initMap();
       this.getLocations();
    }
        
    initMap() {
            const mapEl = document.getElementById('map') as HTMLElement;
            const mapOptions = {
                minZoom: 6,
                zoom: 10,
                disableDefaultUI: true
            };
            this.googleMap = new google.maps.Map(mapEl, mapOptions);
            this.initialZoom = true;
   }
        
   getLocations() {
            this.locationsSource$.subscribe({
                next: (properties: IProperty[]) => {
                    this.properties = properties;
                    this.resetMapMarkers();
                    this.setMapMarkers();
                }
            })
    }
        
setMapMarkers() {
            const bounds = new google.maps.LatLngBounds();
            const infowindow = new google.maps.InfoWindow();
    
            this.markers = this.properties.map((property) => {
                const location = property.location;
                const propertyPrice = property.prices;
                const currencySymbol = getCurrenySymbol(propertyPrice.currency);
    
                const marker = createHTMLMapMarker({
                    latlng: new google.maps.LatLng(
                        Number(location.lattitude),
                        Number(location.longitude)
                    ),
                    map: this.googleMap,
                    label: `${currencySymbol}${propertyPrice.fee_value}`
                });
    
                bounds.extend(marker.getPosition());
    
                /**
                 * *Showing info window on click marker
                 */
                google.maps.event.addListener(marker, 'click', (event: Event) => {
                    const infoContent = createHTMLInfoWindow(property);
                    infowindow.setContent(infoContent);
                    infowindow.setOptions({
                        zIndex: 90
                    });
                    infowindow.open({
                        anchor: marker,
                        map: this.googleMap,
                        shouldFocus: true
                    });
                });
        
                return marker;
            });
    
            /**
             * *Adding marker cluster
             */
            const markerCluster = new MarkerClusterer(this.googleMap, this.markers, {
                zoomOnClick: true,
                maxZoom: 10,
                gridSize: 20,
                styles: [
                    {
                        width: 35,
                        height: 35,
                        anchorIcon: [35, 35],
                        backgroundPosition: '0 0',
                        className: 'custom-clustericon'
                    }
                ]
            });
    
            /**
             * *fitbounds happens asynchronously,
             * *have to wait for a bounds_changed event before setting zoom
             */
            google.maps.event.addListener(
                this.googleMap,
                'bounds_changed',
                (event: Event) => {
                    const mapZoom = this.googleMap.getZoom();
                    if (mapZoom && mapZoom > 15 && this.initialZoom) {
                        this.googleMap.setZoom(10);
                        this.initialZoom = false;
                    }
                }
            );
    
            this.googleMap.fitBounds(bounds);

}
    
resetMapMarkers() {
      for (var i = 0; i < this.markers.length; i++) {
           this.markers[i].setMap(null);
      }
      this.markers = [];
}

try passing null instead of passing void in setmap function尝试通过 null 而不是在 setmap function 中传递 void

refer this link 参考这个链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM