在 Blazor SPA 中嵌入传单地图 [英] Embedding a Leaflet map on a Blazor SPA

查看:15
本文介绍了在 Blazor SPA 中嵌入传单地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How to Embed a Leaflet map on a Blazor SPA, using JSInterop, what objects should be defined, and how to pass data that represents the location clicked on the map, from JavaScript to Blazor

推荐答案

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

Note: The sample code below was created and tested in a WebAssembly Blazor App stand alone...

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

An object reference is required for the nonstatic field, method, or property 'member'

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

Let's create the object class, whose object reference will be passed to your JavaScript's object when initialized. When the user clicks on a location on the map, a click event is triggered for the JS map object, from which the C# object's JSInvokable method is called and passed the latitude and longitude...

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.

Note the definition of an event delegate named Notify. This event is triggered whenever the value of LatLng property is being changed from JavaScript. This allows you to subscribe to the event, and call the StateHasChanged method in order to refresh the UI.

    @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:

Add this CSS rule to the app.css:

    #mapid {
        height: 400px;
    }

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

Note that your JavaScript object is initialized only once and from the OnAfterRenderAsync lifecycle method...

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

Here is the relevant JavaScript code that should be placed at the bottom of the index.html file, below the script element for 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 中嵌入传单地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆