在 Next JS 中显示 arcgis 地图上多个坐标上的信息 Window

Display Info Window on the multiple coordinates on the arcgis map in Next JS

下面是我的下一个 JS 代码,它显示了一个简单的 ArcGIS 地图,其中包含特定坐标上的点或标记。

谁能告诉我如何显示地图上点的弹出窗口/信息 window?例如我点击任何一点,它会在上面打开一个相应的弹出窗口。

import NavBar from '@/components/NavBar'
import axios from 'axios';
import { useRef, useEffect, useState } from 'react';
import { loadModules } from 'esri-loader';

export default function Home({...props}) {
    const [state, setState] = useState('');
    const MapElement = useRef(null)
    const options = {
     url: 'https://js.arcgis.com/4.6/',
     css: true
    };

    useEffect(() => {
        var vehicleData = props.data
        var map, point_symbol;
        loadModules([
            "esri/views/MapView",
            "esri/WebMap",
            "esri/Graphic",          
            "esri/geometry/Point",
            "esri/PopupTemplate",
            "esri/layers/FeatureLayer","dojo/domReady!"
        ],options).then(([ MapView, WebMap, Graphic, Point, PopupTemplate, FeatureLayer]) => {
            const webmap = new WebMap({
                basemap: "gray-vector"
            })

            var map = new MapView({
                map: webmap,
                center:[-6.357768833333333,  53.415487166666665],
                zoom:6,
                container: MapElement.current
            })

            map.popup.autoOpenEnabled = false;
            
            for(var i=0, i_length=vehicleData.length; i<i_length; i++){
                point_symbol = new Point({
                    longitude:vehicleData[i].longitude,
                    latitude: vehicleData[i].latitude,
                    spatialReference: { wkid: 3857 }
                })   
                
                var template = new PopupTemplate({
                    title: vehicleData[i].company,
                    content: vehicleData[i].description
                });
    
                var graphic_symbol = new Graphic({
                    geometry: point_symbol,
                    symbol: {
                        type: "simple-marker",
                        style: "circle",
                        color: "orange",
                        size: "18px",
                        outline: {
                            color: [150, 200, 255],
                            width: 5
                        } 
                    },
                    popupTemplate: template
                });
                map.graphics.add(graphic_symbol)   
            }

            

            map.on("click", function(event) {
                map.popup.open({
                  location: event.mapPoint,
                  
                  features: [graphic_symbol]
                });
              });



            // map.on("click", function(event) {
            //     console.log(vehicleData)
            //     map.popup.open({
            //         location: event.mapPoint,  // location of the click on the view
            //         title: "You clicked here",  // title displayed in the popup
            //         content: "Your description here"  // content displayed in the popup
            //     });
            // });
        })

        return () => {  
            if(!!map) {
                map.destroy()
                map=null
            }
        }
    })

    return (
        
        <div id="home-container"> 
            
        <NavBar />

            <div className="app-wrapper" >
                <div className="app-content">
                    <div className="no-padding">
                        <div className="row gy-4">
                            <div className="col-12">
                                <div style={{height:1000, width:1400}} ref={MapElement}></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div> 

        </div>
    )
}

export async function getServerSideProps(context) {

    let response = await axios(process.env.BASE_URL +'/devices/all',{
        headers : {
            'Authorization' : 'Bearer ' + process.env.TOKEN
        }
    })

    let data = await response.data
    return {
        props : {
            data: data
        }
    }
}

我需要显示与地图上每个标记多个圆相对应的弹出窗口或信息 window。在上面的代码中,API 调用是由 getServerSideProps 完成的,并且数据作为对象数组使用 props 传递给组件。

我可以在地图上显示多个圆圈,但不知道如何显示每个标记对应的信息window?

我认为在您的代码中变量 i 存在上下文问题。当弹出窗口显示 i 的值总是 vehicleData.length.

所以你可以使用 let 而不是 var 来解决上下文问题,但我会建议你另一种方法。

在循环外声明弹出模板 template,并使用我们将在下一步中添加的两个新属性。

var template = new PopupTemplate({
    title: "{company}",
    content: "{description}"
    outFields: ["*"],
    fieldInfos: [
        { fieldName: "company" },
        { fieldName: "description" }
    ]
});

将要显示的信息添加到图形的属性中,像这样,

var graphic_symbol = new Graphic({
    geometry: point_symbol,
    symbol: {
        type: "simple-marker",
        style: "circle",
        color: "orange",
        size: "18px",
        outline: {
            color: [150, 200, 255],
            width: 5
        } 
    },
    popupTemplate: template,
    attributes: {  // <- here
        company: vehicleData[i].company,
        description: vehicleData[i].description
    }
});

最后让点击事件搜索图形,像这样,

map.on("click", function(event) {
    map.popup.open({
        location: event.mapPoint,
        fetchFeatures: true
    });
});

顺便说一句,我只保留了最后一步,因为你故意更改默认值,我在这里没有看到原因,但你必须有一个。

@cabesuon 是对的。您可以删除点击事件并删除 map.popup.autoOpenEnabled = false; 。之后点击图形将默认打开弹出信息。

对于 table 格式,您可能希望对内容使用函数

    // The following snippet shows how to use a function
    // to create a simple node and display it in the popup template content
    let template = new PopupTemplate({
      title: "Population by Gender",
      content: setContentInfo
    });
    
    function setContentInfo(feature){ // feature here is the graphic, you may access its properties for the table
      // create a chart for example
      let node = domConstruct.create("div", { innerHTML: "Text Element inside an HTML div element." });
      return node;
    }