在 Blazor SPA 中嵌入传单地图

Posted

技术标签:

【中文标题】在 Blazor SPA 中嵌入传单地图【英文标题】:Embedding a Leaflet map on a Blazor SPA 【发布时间】:2021-02-10 19:43:43 【问题描述】:

如何在 Blazor SPA 中嵌入 Leaflet 地图,使用 JSInterop,应定义哪些对象,以及如何将表示在地图上单击的位置的数据从 javascript 传递到 Blazor

【问题讨论】:

你试过github.com/Mehigh17/BlazorLeaflet 【参考方案1】:

注意:下面的示例代码是在独立的 WebAssembly Blazor 应用程序中创建和测试的......

非静态字段、方法或属性“成员”需要对象引用

让我们创建对象类,它的对象引用将在初始化时传递给您的 JavaScript 对象。当用户点击地图上的某个位置时,会触发 JS 地图对象的点击事件,从中调用 C# 对象的 JSInvokable 方法并传递经纬度...

GCSService.cs

public class GCSService

    public GCSService() 
    public event Func<Task> Notify;
    public string LatLng  get; set; 

    [JSInvokableAttribute("GetLatLng")]
    public async Task GetLatLng(string latLng)
    
       LatLng = latLng;

       if (Notify != null)
       
           await Notify?.Invoke();
       
    

请注意名为 Notify 的事件委托的定义。该事件被触发 每当从 JavaScript 更改 LatLng 属性的值时。这允许您订阅事件,并调用 StateHasChanged 方法以刷新 UI。

Index.razor

    @page "/"
    @implements IDisposable
    @inject IJSRuntime JSRuntime
    
    @if (GCS != null)
    
        <div>Latitude and Longitude: @GCS.LatLng</div>
    
    <div id="mapid"></div>
    
    @code
        private DotNetObjectReference<GCSService> objRef;
        private GCSService GCS;
    
        protected override async Task OnAfterRenderAsync(bool firstRender)
        
            if (firstRender)
            
                await JSRuntime.InvokeAsync<object>(
                "leafletJsFunctions.initialize", objRef);
            
            base.OnAfterRender(firstRender);
        
    
        protected override void OnInitialized()
        
            GCS = new GCSService();
    
            objRef = DotNetObjectReference.Create(GCS);
    
            GCS.Notify += OnNotify;
        
        
        public void Dispose()
        
            GCS.Notify -= OnNotify;
    
            objRef?.Dispose();
        
    
        public async Task OnNotify()
        
            await InvokeAsync(() =>
            
                StateHasChanged();
            );
       
     

将此 CSS 规则添加到 app.css:

    #mapid 
        height: 400px;
    

请注意,您的 JavaScript 对象仅初始化一次,并且从 OnAfterRenderAsync 生命周期方法...

这里是相关的 JavaScript 代码,应该放在 index.html 文件的底部,在 blazor.webassembly.js 的脚本元素下方

<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
        integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
        crossorigin="">

</script>

<script type="text/javascript">
   
    window.leafletJsFunctions = 

        initialize: function (dotnetHelper) 

            var mymap = L.map('mapid').setView([51.505, -0.09], 13);

            L.tileLayer('https://api.mapbox.com/styles/v1/id/tiles/z/x/y?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', 
                maxZoom: 18,
                attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
                    '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
                    'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
                id: 'mapbox/streets-v11',
                tileSize: 512,
                zoomOffset: -1
            ).addTo(mymap);

            L.marker([51.5, -0.09]).addTo(mymap)
                .bindPopup("<b>Hello world!</b><br />I am a popup.").openPopup();

            L.circle([51.508, -0.11], 500, 
                color: 'red',
                fillColor: '#f03',
                fillOpacity: 0.5
            ).addTo(mymap).bindPopup("I am a circle.");

            L.polygon([
                [51.509, -0.08],
                [51.503, -0.06],
                [51.51, -0.047]
            ]).addTo(mymap).bindPopup("I am a polygon.");

            var popup = L.popup();

            function onMapClick(e) 
                // Invoke the instance method GetLatLng, passing it the
                // Latitude and Logitude value     
                return dotnetHelper.invokeMethodAsync('GetLatLng', 
                                            e.latlng.toString());
             

            mymap.on('click', onMapClick);
       
     ;
  </script>

【讨论】:

以上是关于在 Blazor SPA 中嵌入传单地图的主要内容,如果未能解决你的问题,请参考以下文章

奇怪的PHP谷歌地图嵌入在iframe中的行为

从嵌入式 Blazor 组件中检索数据

Blazor_WASM之2:Razor语法

如何在现有的Vue项目中嵌入 Blazor项目?

在自己的网页中嵌入百度地图

如何在片段中嵌入谷歌地图?