Blazor组件自做五: 使用JS隔离封装Google地图

运行截图

演示地址

正式开始

1. 谷歌地图API

谷歌开发文档

开始学习 Maps JavaScript API 的最简单方法是查看一个简单示例。以下示例显示以澳大利亚新南威尔士州悉尼为中心的地图。

异步加载例子

JS代码

let map;

function initMap() {
map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8,
});
}

HTML代码

<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<link rel="stylesheet" type="text/css" href="./style.css" />
<script src="./index.js"></script>
</head>
<body>
<div id="map"></div> <!-- Async script executes immediately and must be after any DOM elements used in callback. -->
<script
src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap&v=weekly"
async
></script>
</body>
</html>

同步加载例子。我们省略了加载 API async 的标签中的属性script,也省略了回调参数

JS代码

const map = new google.maps.Map(document.getElementById("map"), {
center: { lat: -34.397, lng: 150.644 },
zoom: 8,
});

HTML代码

<!DOCTYPE html>
<html>
<head>
<title>Synchronous Loading</title>
<script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>
<link rel="stylesheet" type="text/css" href="./style.css" />
</head>
<body>
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&v=weekly"></script>
<script src="./index.js"></script>
</body>
</html>

Polyfill 是一块代码(通常是 Web 上的 JavaScript),用来为旧浏览器提供它没有原生支持的较新的功能。

比如说 polyfill 可以让 IE7 使用 Silverlight 插件来模拟 HTML Canvas 元素的功能,或模拟 CSS 实现 rem 单位的支持,或 text-shadow,或其他任何你想要的功能。

由于blazor能运行的浏览器都是比较新的,所以我们不需要运行此polyfill.min.js脚本.

2. 在文件夹wwwroot/lib,添加google子文件夹,添加map.js文件.

2.1 用代码方式异步加载API,脚本生成新的 head > script 元素添加到页面文档,使用异步加载回调 initGoogleMaps 方法初始化地图.

export function addScript(key, elementId, dotnetRef, backgroundColor, controlSize) {
if (!key || !elementId) {
return;
} let url = "https://maps.googleapis.com/maps/api/js?key=";
let scriptsIncluded = false; let scriptTags = document.querySelectorAll('head > script');
scriptTags.forEach(scriptTag => {
if (scriptTag) {
let srcAttribute = scriptTag.getAttribute('src');
if (srcAttribute && srcAttribute.startsWith(url)) {
scriptsIncluded = true;
return true;
}
}
}); if (scriptsIncluded) { //防止多次向页面添加 JS 脚本.Prevent adding JS scripts to page multiple times.
if (window.google) {
initMaps(elementId); //页面已导航. Page was navigated
}
return true;
} url = url + key + "&callback=initGoogleMaps&libraries=&v=weekly";
let script = document.createElement('script');
script.src = url;
script.defer = true;
document.head.appendChild(script);
return false;
}

2.2 方法初始化地图,以及dispose().

export function initMaps(elementId) {
var latlng = new google.maps.LatLng(40.26982, -3.758269);
var options = {
zoom: 14, center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(elementId, options);
console.log(map);
return map;
}
//Remove elementId with data
function removeElementIdWithDotnetRef(dict, elementId) {
for (let i = 0; i < dict.length; i++) {
if (dict[i].key === elementId) {
dict.splice(i, 1);
break;
}
}
}
//Dispose
export function dispose(elementId) {
if (elementId) {
let mapWithDotnetRef = getElementIdWithDotnetRef(_mapsElementDict, elementId);
mapWithDotnetRef.map = null;
mapWithDotnetRef.ref = null; removeElementIdWithDotnetRef(_mapsElementDict, elementId);
}
}

3. 打开Components文件夹 , 新建 Google文件夹,添加 Map.razor 文件.

将来也许会添加更多API封装,类似云盘/文档,所以建立文件夹备用.

由于不确定是否完成初始化,网络或者各种原因,故这里做了一个低级而万能的while循环检测map是否载入成功.如果各位小伙伴还有更优雅的方法,欢迎在底下留言,互通有无,cv万岁!

while (!(await Init()))
{
await Task.Delay(500);
}

其中一个参数是 [Parameter] public string? Key { get; set; },也就是你的 GoogleKey 在开发者后台可以获取,可以组件形式调用的时候设置, 不设置,即为空则在 IConfiguration 服务获取 "GoogleKey" , 默认在 appsettings.json 文件配置 "GoogleKey"="xxxxxxx"即可.

页面使用调用注入的服务IConfiguration使用如下代码

@inject IConfiguration config

完整代码如下

@implements IAsyncDisposable
@inject IJSRuntime JS
@namespace Blazor100.Components
@inject IConfiguration config <div @ref="map" style="@Style">
</div>
<button class="btn btn-primary" type="button" onclick="@(async()=>await OnBtnClick())">Reset</button> @code{ /// <summary>
/// 获得/设置 错误回调方法
/// </summary>
[Parameter]
public Func<string, Task>? OnError { get; set; } /// <summary>
/// 获得/设置 GoogleKey<para></para>
/// 为空则在 IConfiguration 服务获取 "GoogleKey" , 默认在 appsettings.json 文件配置
/// </summary>
[Parameter]
public string? Key { get; set; } /// <summary>
/// 获得/设置 style
/// </summary>
[Parameter]
public string Style { get; set; } = "height:700px;width:100%;"; ElementReference map { get; set; } private IJSObjectReference? module;
private string key = String.Empty; protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
key = Key ?? config["GoogleKey"];
module = await JS.InvokeAsync<IJSObjectReference>("import", "./lib/google/map.js");
while (!(await Init()))
{
await Task.Delay(500);
}
}
} public async Task<bool> Init() => await module!.InvokeAsync<bool>("addScript", new object?[] { key, map, null, null, null }); public async Task OnBtnClick() => await module!.InvokeVoidAsync("addScript", new object?[] { key, map, null, null, null }); async ValueTask IAsyncDisposable.DisposeAsync()
{
if (module is not null)
{
//await module.InvokeVoidAsync("destroy", Options);
await module.DisposeAsync();
}
}
}

4. Pages文件夹添加MapsPage.razor文件,用于演示组件调用.

4.1 代码后置

代码后置是微软的一项技术,也是我们编写 .NET Core常用的编码方式。具体方式就像.razor和代码文件.cs两个文件相互关联构成一个页面。一般情况下,.razor文件中没有代码、只有组件和HTML代码,而在.cs文件中编写相关的代码。这样做的好处就是代码和页面内容分离,使代码更清晰。

阅读:分部类

现在尝试使用代码后置的写法,razor只写Html和路由

@page "/maps"

<h3>谷歌地图 Maps</h3>

<p>@message</p>

<Map OnError="@OnError" />

右键添加cs文件,命名为 MapsPage.razor.cs , 文件名命名方式为razor页面文件名全名后加.cs, 如果解决方案资源管理器默认开启了文件嵌套,这两个文件会合并在一起并且前面有三角符号,展开可看到后置的cs代码.

好了,现在终于可以正常愉快的写cs代码了,不用继续忍受VS2022的莫名其妙的红线和编辑razor文件带来的内存泄漏干扰, .

MapsPage.razor.cs 完整代码

using Blazor100.Components;

namespace Blazor100.Pages;

/// <summary>
/// 谷歌地图 Maps
/// </summary>
public sealed partial class MapsPage
{ private string message; private Task OnError(string message)
{
this.message = message;
StateHasChanged();
return Task.CompletedTask;
} }

5. _Imports.razor加入一行引用组件的命名空间.

@using Blazor100.Components

6. 首页引用组件演示页 <MapsPage />或者 Shared/NavMenu.razor 添加导航

<div class="nav-item px-3">
<NavLink class="nav-link" href="maps">
谷歌地图
</NavLink>
</div>

7. F5运行程序

8. 谷歌地图API还有若干的功能没有封装进来,此处只是抛砖引玉,后续版我会持续加进正式开源组件Densen.Component.Blazor中.

至此,使用JS隔离封装Google地图大功告成! Happy coding!

Blazor组件自做系列

Blazor组件自做一 : 使用JS隔离封装viewerjs库

Blazor组件自做二 : 使用JS隔离制作手写签名组件

Blazor组件自做三 : 使用JS隔离封装ZXing扫码

Blazor组件自做四: 使用JS隔离封装signature_pad签名组件

Blazor组件自做五: 使用JS隔离封装Google地图<03-24>

Blazor组件自做六: 使用JS隔离封装Baidu地图<03-25>

Blazor组件自做七: 使用JS隔离制作定位/持续定位组件<03-26>

Blazor组件自做八: 使用JS隔离封装屏幕键盘kioskboard.js组件<03-27>

项目源码 Github | Gitee

Blazor组件自做五 : 使用JS隔离封装Google地图的更多相关文章

  1. Blazor组件自做六 : 使用JS隔离封装Baidu地图

    1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加baidu子文件夹,添加baidumap.js文件 2.1 跟上一篇类似,用代码方式异步加载API,脚本生成新的 body > ...

  2. Blazor组件自做八 : 使用JS隔离封装屏幕键盘kioskboard.js组件

    1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加kioskboard子文件夹,添加kioskboards.js文件 2.1 常规操作,懒加载js库, export function ...

  3. Blazor组件自做一 : 使用JS隔离封装viewerjs库

    Viewer.js库是一个实用的js库,用于图片浏览,放大缩小翻转幻灯片播放等实用操作 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazo ...

  4. Blazor组件自做三 : 使用JS隔离封装ZXing扫码

    Blazor组件自做三 : 使用JS隔离封装ZXing扫码 本文基础步骤参考前两篇文章 Blazor组件自做一 : 使用JS隔离封装viewerjs库 Blazor组件自做二 : 使用JS隔离制作手写 ...

  5. Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件

    运行截图 演示地址 响应式演示 感谢szimek写的棒棒的signature_pad.js项目, 来源: https://github.com/szimek/signature_pad 正式开始 1. ...

  6. Blazor组件自做二 : 使用JS隔离制作手写签名组件

    Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...

  7. Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (3)

    接上篇 Blazor组件自做九: 用20行代码实现文件上传,浏览目录功能 (2) 7. 使用配置文件指定监听地址 打开 appsettings.json 文件,加入一行 "UseUrls&q ...

  8. Blazor组件自做十一 : File System Access 文件系统访问 组件

    Blazor File System Access 文件系统访问 组件 Web 应用程序与用户本地设备上的文件进行交互 File System Access API(以前称为 Native File ...

  9. Blazor组件自做七 : 使用JS隔离制作定位/持续定位组件

    1. 运行截图 演示地址 2. 在文件夹wwwroot/lib,添加geolocation子文件夹,添加geolocation.js文件 本组件主要是调用浏览器两个API实现基于浏览器的定位功能,现代 ...

随机推荐

  1. 【SQL】数据库运维实习工作经验

    1.导入表格的时候回出现类型不对应的问题,T-SQL代码如下: USE zzzj2017 ALTER TABLE CJ ALTER COLUMN 付款时间 datetime    2.删除 USE s ...

  2. 阿里云CND加速

    1: :2: 3: 4: 5: 6: 7:将解析信息如实添加 8:如果报错添加 CNAME 记录提示和 A 记录冲突,也就是说如果你要添加 CDN 全站加速,域名解析那里就不能再有 A 记录了, 只有 ...

  3. laravel 分页支持搜索功能

  4. 微信小程序 app.js globalData 赋值报错

    //success方法要用用success: res => {}的格式 success: res => { } //赋值报错 success:function(e){ } //报错内容: ...

  5. 【图片+代码】:GCC 链接过程中的【重定位】过程分析

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  6. ES77

    PUT rr_bd202_chaos_20211220{ "aliases" : { "rr_bd202_chaos_pgold":{} }, "ma ...

  7. Gin 09 HTTP 重定向

    gin http 重定向有两种方法,重写url 和 不重写的跳转.两种方法,gin 通过两个内置方法实现: demo package main import ( "github.com/gi ...

  8. 利用DNSLog实现无回显注入

    测试一些网站的时候,一些注入都是无回显的,我们可以写脚本来进行盲注,但有些网站会ban掉我们的ip,这样我们可以通过设置ip代理池解决, 但是盲注往往效率很低,所以产生了DNSlog注入 DNSLOG ...

  9. tomcat启动 ssm项目出现乱码的解决

    0.乱码产生原因:编码和解码的方式是不同 1.出现乱码的解决方式[推荐]: 在tomcat 的配置文件web.xml 中添加上请求编码过滤器: <!-- 请求编码过滤器 --> <f ...

  10. Spring事件监听机制源码解析

    Spring事件监听器使用 1.Spring事件监听体系包括三个组件:事件.事件监听器,事件广播器. 事件:定义事件类型和事件源,需要继承ApplicationEvent. package com.y ...