首页 > 解决方案 > 重新渲染地图时如何更新 Azure Maps 上的弹出窗口?

问题描述

我目前正在为我的公司开发一个内部 CRM 应用程序。它使用 Blazor 构建,并利用 Azure Maps javascript SDK。我正在使用 Azure Maps 来可视化我公司游戏玩家收集的地图项。根据 Microsoft 提供的文档,所有地图设置都是在 javascript 中完成的。该地图有一个用于显示点的符号层,以及一个用于渲染给定玩家行进路径的线层。此外,我们正在生成玩家收集统计数据的摘要(速度、距离和收集之间的时间)。这个组件所在的页面有一个 DateRangePicker、一个不同项目类型的下拉菜单和一个运行查询的按钮。目前,该网页的用户可以更改日期范围和项目类型并重新运行查询。这会导致摘要以及包含所有点和线的地图被正确地重新渲染。但是,当重新渲染地图时,附加到点的弹出窗口不再在地图上,或者至少对鼠标事件没有响应。如果有人对如何在地图渲染中保留和更新我的弹出窗口有任何想法,他们将不胜感激。

标签: javascript.netblazorazure-mapsblazor-jsinterop

解决方案


很高兴在这里您解决了您的问题并为其他人发布了答案。一项建议是,尽可能重用地图实例和图层。您可以在您的应用程序中运行一次上面的代码,然后在将来使用datasource.setShapes并传递新点。这将自动更新地图上的数据。如果添加新数据时弹出窗口打开,只需将其关闭即可。看起来也可以围绕您的点转换代码/速度计算进行一些优化。这是您的代码的修改版本,它可能会提供一些性能增强。

window.adminMap = (() => {

    let map;
    let datasource;
    let point;
    let popup;
    let lineLayer;

    const setupItemsMap = (subscriptionKey, mapItems) => {

        if (map != null) {
            map.dispose();
        }

        map = new atlas.Map('itemsMap', {
            center: [mapItems[0].coordinate.long, mapItems[0].coordinate.lat],
            centerOffest: [0, 0],
            zoom: 15,
            pitch: 90,
            style: 'road',
            language: 'en-US',
            view: 'Auto',
            authOptions: {
                authType: 'subscriptionKey',
                subscriptionKey: subscriptionKey
            }
        });

        map.events.add('ready', () => {

            //Create a data source and add it to the map.
            datasource = new atlas.source.DataSource(null, {
                lineMetrics: true
            });
            map.sources.add(datasource);
            
            lineLayer = new atlas.layer.LineLayer(datasource, null, {
                strokeWidth: 5,
                //strokeGradient: speedGradient
            });
            
            //Create a line layer and pass in a gradient expression for the strokeGradient property.
            map.layers.add(lineLayer);

            //Create a layer to render each data point along the path.
            var pointLayer = new atlas.layer.SymbolLayer(datasource, null, {
                //Only render point data in this layer, not the points of the line.
                filter: ['==', ['geometry-type'], 'Point']
            });

            //Create a popup. *This needs to update with the rest of the map!
            popup = new atlas.Popup();
            popup.open(map);

            map.layers.add(pointLayer);

            map.events.add('click', pointLayer, pointClicked);

            //Add mapItems to data source.
            setMapItems(mapItems);
        });
    }
    
    const setMapItems = (mapItems) => { 
        let points = [];        
        let previous;
        let point;
        
        for(let i = 0, len = mapItems.length; i < len; i++){
                    
            point = new atlas.data.Feature(new atlas.data.Point([mapItem.coordinate.long, mapItem.coordinate.lat]), {
                collectedAt: mapItem.collectedAt,
                speed: 0
            });
            
            if(previous){
                point.properties.speed = atlas.math.getSpeedFromFeatures(previous, point, "collectedAt", "milesPerHour", 1);
            }
            
            points.push(point);
            
            previous = point;
        }

        var line = createLineFrom(points);          
        
        //Calculate a color gradient expression based on the speed of each data point.
        lineLayer.setOptions({
            strokeGradient: calculateGradientExpression(points, line)
        });
        
        points.push(line);
        
        //Add data to data source using setShapes. This clears and adds the data and only triggers one re-render of the map.
        datasource.setShapes(points);
        
        if(popup){
            popup.close();
        }       
    }
}

推荐阅读