网站首页 > 知识剖析 正文
运行截图
演示地址
https://blazor.app1.es/maps
正式开始
1. 谷歌地图API
谷歌开发文档
https://developers.google.com/maps/documentation/javascript/overview
开始学习 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" />
<AttributeTable Items="@GetAttributes()" />
右键添加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;
}
/// <summary>
/// 获得属性方法
/// </summary>
/// <returns></returns>
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
{
new AttributeItem("Style","地图大小", "height:700px;width:100%;","string"),
new AttributeItem("Init","初始化", "-","Task<bool>"),
new AttributeItem("OnError","错误信息回调", "-","Func<string, Task>"),
};
}
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隔离封装signature_pad签名组件
Blazor组件自做八:使用JS隔离封装屏幕键盘kioskboard.js组件
项目源码Github|Gitee
https://github.com/densen2014/Blazor100
https://gitee.com/densen2014/Blazor100
Blazor100: Blazor入门100天
猜你喜欢
- 2024-11-14 vue.js正确使用百度地图的方案 vue百度地图自定义控件
- 2024-11-14 七爪源码:如何在 JavaScript 中将 JSON 转换为地图
- 2024-11-14 在地图上创建热力图的方法 怎么用热力图选址
- 2024-11-14 快速了解 ES6 的Map与WeakMap es6 map使用场景
- 2024-11-14 Vue3 + TS + Leafletjs 打造企业级原神大地图
- 2024-11-14 好东西一起用,Cesium.js真是让3D地图尖叫的神奇框架!
- 2024-11-14 为 Next.js 项目创建站点地图文件
- 2024-11-14 JavaScript 轻松获取 Map 中的某个 key
- 2024-11-14 何时使用 Map 来代替普通的 JS 对象
- 2024-11-14 看了几十篇论文实现了个专业算法,用threejs做了个人员定位系统
- 04-29php开发者composer使用看这一篇就够了
- 04-29引用和变量声明在不同语言中的实作
- 04-29PHP 没你想的那么差
- 04-29Ubuntu linux 上的 Nginx 和 Php 安装
- 04-29CentOS下通过yum搭建lnmp(单版本PHP)
- 04-29为什么 PHP8 是个高性能版本
- 04-29PHP8函数包含文件-PHP8知识详解
- 04-29使用无参数函数进行命令执行
- 最近发表
- 标签列表
-
- xml (46)
- css animation (57)
- array_slice (60)
- htmlspecialchars (54)
- position: absolute (54)
- datediff函数 (47)
- array_pop (49)
- jsmap (52)
- toggleclass (43)
- console.time (63)
- .sql (41)
- ahref (40)
- js json.parse (59)
- html复选框 (60)
- css 透明 (44)
- css 颜色 (47)
- php replace (41)
- css nth-child (48)
- min-height (40)
- xml schema (44)
- css 最后一个元素 (46)
- location.origin (44)
- table border (49)
- html tr (40)
- video controls (49)