@asymmetrik/ngx-leaflet (英语)
Angular.io的叶片包. 为将Leaflet v.7.x和v1.x整合入Angular.io项目提供灵活而可扩展的组件. 支持Angular v18,并在Angular-CLI基站项目中使用.
注: 这是将在 @asymmetrik namespace 下发布的此软件包的最后一个版本 . 此版本和未来版本将在命名空间下发布 : @ bluehalo
目录
安装
通过 npm(或纱线) 安装软件包及其对等依赖性 :
npm install leaflet
npm install @asymmetrik/ngx-leaflet
如果您打算在打字项目(使用打字)中使用此库, 您需要安装传单打字:
npm install --save-dev @types/leaflet
如果您想要运行演示, 克隆寄存器, 执行 npm install, (中文(简体) ), npm run demo 然后转到http://localhost:4200
不使用Angular.io的最新版本吗? 进去看看 变化情况 为您的项目找到正确的版本.
使用量
要使用这个库,需要经过的几个设置步骤,根据你的应用环境(如Webpack,ngCli,SystemJS等)而有所不同. 这些步骤一般是:
- 安装Leaflet,这个库,以及可能的Leaflet打字机(见上文).
- 导入叶片样式表
- 将 Leaflet 模块导入您的 Angular 项目
- 创建和配置地图(见下文和/或演示文件)
导入叶片样式表
要使用传单,请将传单样式表加载到您的应用程序中.
如果你已经通过npm安装, 你需要加载 ./node_modules/leaflet/dist/leaflet.css。 。 。 .
如何包含样式表将取决于您的特定设置 。 以下是几个例子:
从 HTML 直接导入
如果您只是构建一个网页,而不是为您的 cs 使用捆绑器, 您会希望直接导入 HTML 页面中的 cs 文件 .
<head>
...
<link rel="stylesheet" type="text/css" href="./node_modules/leaflet/dist/leaflet.css">
...
</head>
配置 Webpack 样式加载器
如果您正在使用Webpack, 您需要导入 cs 文件并配置一个样式加载器 . 您可以使用此应用程序中包含的演示作为参考 .
一般来说 vendor.ts数字 :
import 'leaflet/dist/leaflet.css';
然后在你的网页包配置文件中:
{
...
"module" : {
loaders: [
...
{ test: /\.css$/, loaders: [ 'style-loader', 'css-loader' ] },
...
]
},
...
}
在角 CLI 中添加样式
如果您正在使用 Angular CLI, 您需要将 Leaflet CSS 文件添加到包含在 angular.json
{
...
"styles": [
"styles.css",
"./node_modules/leaflet/dist/leaflet.css"
],
...
}
导入代码依赖和模块
这个项目使用UMD输出,包括打字. 所以,你不应该做 任何特殊的事情来使用它 如果你正在构建你的项目 在Typescript.
Typescription Angular.io 模块导入
在可以使用您 Angular.io app中的模块之前,您需要在您的应用程序中导入模块(以及潜在的正在使用的模块).
比如说,你 app.module.ts,添加:
import { LeafletModule } from '@asymmetrik/ngx-leaflet';
...
imports: [
...
LeafletModule
]
...
可能的话,你还需要将它导入到将实际使用ngx-leaflet指令的组件模块.
更多详情请参见Angular.io 模块索引(https://angular.io/guide/ngmodule (英语)) (中文(简体) ). 在这种情况下,在 my-module.module.ts,添加:
import { LeafletModule } from '@asymmetrik/ngx-leaflet';
...
imports: [
...
LeafletModule
]
...
不使用打字符吗 ?
你勇敢的灵魂.
该代码使用UMD导出.
捆绑是作为构件的一部分产生的(npm run build)并放入./dist dir.
您应该能够导入的是使用您使用的任意模块系统/构建器, 即使您没有使用 Typescript.
创建和配置地图
一旦依赖性安装并导入 LeafletModule,你准备在你的页面上添加地图.
要获得基本地图才能工作,必须:
- 应用
leaflet将指令(见下文示例)归属到现有的 DOM 元素. - 以高度样式样式映射 DOM 元素 。 否则,它会以0像素高度渲染出.
- 提供初始缩放/中和分层,通过
leafletOptions或通过约束leafletZoom, (中文(简体) ),leafletCenter,以及leafletLayers。 。 。 .
模板 :
<div style="height: 300px;"
leaflet
[leafletOptions]="options">
</div>
示例传单选项对象:
options = {
layers: [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' })
],
zoom: 5,
center: latLng(46.879966, -121.726909)
};
对小册子选项的修改在初始设定后会被忽略.
这是因为这些选项被传入了地图构建器,所以无论如何都无法被更改.
因此,在地图被创建之前确保对象存在.
您将在 ngOnInit 或用 *ngIf 直到您可以创建选项对象.
添加层控件
这个 [leafletLayersControl] 输入绑定赋予了您在地图上添加层控件的能力.
分层控制让用户切换分层并覆盖上下.
模板 :
<div style="height: 300px;"
leaflet
[leafletOptions]="options"
[leafletLayersControl]="layersControl">
</div>
示例层控制对象 :
layersControl = {
baseLayers: {
'Open Street Map': tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' }),
'Open Cycle Map': tileLayer('https://{s}.tile.opencyclemap.org/cycle/{z}/{x}/{y}.png', { maxZoom: 18, attribution: '...' })
},
overlays: {
'Big Circle': circle([ 46.95, -122 ], { radius: 5000 }),
'Big Square': polygon([[ 46.8, -121.55 ], [ 46.9, -121.55 ], [ 46.9, -121.7 ], [ 46.8, -121.7 ]])
}
}
您可以添加任何您想要的叶片层 overlays 地图.
这包括标记,形状,地理json,来自其他库的自定义地层等.
添加自定义层( 基层、 标记、 形状等)
在地图上添加地层有几种不同的方式.
您可以在地图上添加图层( 底板层、 标记层或自定义地层), 而不使用 [leafletLayers] 指令.
模板 :
<div style="height: 300px;"
leaflet
[leafletOptions]="options"
[leafletLayers]="layers">
</div>
图层数组 :
layers = [
circle([ 46.95, -122 ], { radius: 5000 }),
polygon([[ 46.8, -121.85 ], [ 46.92, -121.92 ], [ 46.87, -121.8 ]]),
marker([ 46.879966, -121.726909 ])
];
您也可以使用 [leafletLayer] 指令.
使用此方法,您可以使用 *ngFor 财务报告和审定财务报表 *ngIf 以控制图中是否添加或去除各个图层.
模板 :
<div style="height: 300px;"
leaflet
[leafletOptions]="options">
<div *ngIf="showLayer" [leafletLayer]="layer"></div>
</div>
图层 :
layer = circle([ 46.95, -122 ], { radius: 5000 });
使用 [leafletLayers] 动态更改映射图层
图层输入(阵列和地图)可变 此插件的上个版本将层数组和层控制对象视为不可变的数据结构. 我们改变了这种行为. 现在,可变的改变
leafletLayers, (中文(简体) ),leafletBaseLayers,以及leafletLayersControl检测输入.
该插件现在使用内部ngx可执行性,而密钥/值则不同来检测并跟踪可变数据结构的变化. 这种方法需要深入比较数据结构的内容(当内容真的很大时可能很慢). 对于不可改变的数据结构来说,只需要进行最高一级实例平等检查(速度更快). 这种改变是向后兼容的,其动机是反馈和混淆. 虽然对某些使用情况有业绩影响,但这种办法更直观.
当有许多地层与地图相接时,至少有两种改善性能的良好方法. 首先,可以使用"OnPush"变换检测策略. 演示中有这方面的例子. 其次,你可以将大量地层包入叶片地层组,这将减少插件在diffs期间实际需要跟踪的地层数量.
与传单活动合作
通常,您会想要根据地图点击或其他Leaflet交互来做出修改. Ngx- 叶插件支持多个 地图事件 财务报告和审定财务报表 层事件 载于API部分.
不过,你偶尔可能需要处理没有通过插件被曝光的事件. 当发生这种情况时,您需要了解Zones和更改检测工作如何确保您的事件处理工作如所预期. 看看这个 关于更改检测的说明 更多细节. 这是设计上的,也是在使用第三方图书馆和Angular时处理的常事.
API 密码
本节更详细地记录了该图书馆中的指示的功能.
高级地图配置
有几种输入绑定可用于配置地图.
<div leaflet style="height: 300px;"
[leafletOptions]="options"
[leafletPanOptions]="panOptions"
[leafletZoomOptions]="zoomOptions"
[leafletZoomPanOptions]="zoomPanOptions"
[leafletFitBoundsOptions]="fitBoundsOptions">
</div>
[叶取可选
初始传单地图选项的输入装订(见 叶子 (中文(简体) ). 这些选项最初只能设定,因为它们被用于创建地图. 后来的更改被忽略了.
[叶发潘可选
对 pan 选项绑定输入( 见 叶子 (中文(简体) ). 当泛操作被引用时,这些选项会被存储和使用.
[叶发柔姆可选
输入绑定缩放选项( 见 叶子 (中文(简体) ). 当引用缩放操作时,这些选项会被存储和使用.
[叶子ZoomPan选项]
输入绑定缩放/宽选项(见 叶子 (中文(简体) ). 当引用缩放/泛操作时,这些选项会被存储和使用.
[叶发FitBounds可选
FitBunds 选项的输入绑定(参见 叶子 (中文(简体) ). 当启动 FitBounds 操作时,这些选项会被存储和使用.
动态变化的缩放级,中位,相接地等.
<div leaflet style="height: 300px;"
[leafletOptions]="options"
[(leafletZoom)]="zoom"
[(leafletCenter)]="center"
[leafletFitBounds]="fitBounds">
</div>
[(叶子Zoom)]:数量
对映射级进行输入和输出绑定 .
[叶发马克斯祖姆]:号码
对地图的最大缩放级别进行输入绑定.
[叶发明祖姆:编号
对地图最小缩放级别进行输入绑定.
[(叶片中心)]: 连线
输入和输出绑定地图中心位置 .
注:中心/区域操作可能相互干扰
快速相继应用的Zoom/Center操作可能互相干扰或取消. 如果两个更改同时被取出,则组件应用这些更改作为映射. setView () 操作,以确保两者都得到处理. 此外,如果应用了不允许的缩放关卡或中心(例如,超过最大缩放关卡或超出最大界限),Leaflet将决定新的值.
[叶发FitBounds]:"长生不老"
输入绑定 a LatLngBounds 使用 Map.setFitBounds()。 。 。 .
这个操作没有输出绑定,因为输入适中Bunds通常会产生稍有不同的映射边框.
[叶发麦克斯布恩斯]
输入绑定 a LatLngBounds 使用 Map.setMaxBounds()。 。 。 .
简单层管理: 设置底板
在名为“ 地图” 的地图上设置底板时, 有方便输入绑定 [leafletBaseLayers]。 。 。 .
您也可提供 [leafletLayersControlOptions] 如果您想要显示地图上的控件,允许您在底板上切换.
如果您计划显示的不仅仅是底板, 您应该使用其中描述的更高级的层控件 高级层管理 见下文.
以基本地图设置为例,请查看 简单基层 演示.
<div leaflet style="height: 300px;"
[leafletOptions]="options"
[leafletBaseLayers]="baseLayers"
[leafletLayersControlOptions]="layersControlOptions">
</div>
控制。 图层对象
输入绑定 Control.LayersObject 将被同步到地图.
baseLayers: {
'layer1': Layer,
'layer2': Layer
}
更改时,组件会将地图上的基础Layers与此对象的地层同步.
同步是通过跟踪当前底板和在变化上,搜索地图来进行,以查看当前底板是否被添加到地图上.
如果它发现一个仍然被添加到地图中的基底层,它会假设这仍然是基底层并离开.
如果地图上找不到任何基底层,它就会增加它发现的第一层 Control.LayersObject 用它来做新的基底.
用实例平等来比较图层.
如果您使用此指令, 您仍然可以手动使用 [leafletLayers] 指令,但您将无法使用 [leafletLayersControl] 指令.
这个指令内部使用地层控制,所以如果加上两者,它们就会互相干扰.
因为它用 control.layers 在引擎盖下,你仍然可以提供层控件的选项.
[叶片Layers控制选项]
输入绑定控制。 层选项( 参见 叶子 (中文(简体) ). 这些选项被传递到创建时的地层控制构建器中.
高级地层管理:地层和地层控制
这个 [leafletLayers] 财务报告和审定财务报表 [leafletLayersControl] 输入绑定让您直接访问操纵层和层控.
当数组绑定到 [leafletLayers] 更改时,指令将把地图上的图层同步到数组中的图层.
这包括地砖地层和所增加的任何形状.
这个 [leafletLayersControl] 输入绑定允许您提供一组基层和上覆层,这些基层和上覆层可以使用层控件在传单内管理.
当用户通过Leaflet来操纵控制时,Leaflet会自动管理地层,但输入绑定地层阵列不会被更新来反映这些变化.
所以,用 [leafletLayers] 在地图上添加层集.
还有,用 [leafletLayersControl] 允许用户可选地打开/关闭层/覆盖.
作为使用层控件的例子,您应当检查 层和层控件 演示.
<div leaflet style="height: 300px;"
[leafletOptions]="options"
[leafletLayers]="layers"
[leafletLayersControl]="layersControl"
[leafletLayersControlOptions]="layersControlOptions">
</div>
[叶子Layers]:地层[
输入绑定要同步(并可见)于地图的所有层的数组.
更改时,组件会将地图上的地层与这个阵列中的地层同步. 同步是通过选择性地添加或去除地层来实现的. 用实例平等来比较图层. 由于地图是如何同步的,无法保证图层的顺序随着变化而保持一致.
[叶发Layers Control]:控制. 层
输入绑定控制器 。 层规格 。 对象包含控件的两个构造参数的每个属性 。 层构造器.
layersControl: {
baseLayers: {
'layerName': Layer
},
overlays: {
'overlayName': Layer
}
}
[叶片Layers控制选项]
输入绑定控制。 层选项( 参见 叶子 (中文(简体) ). 这些选项在创建时传递到构建器中.
高级层管理:单个层和 *ngFor / *ng 如果
这个 [leafletLayer] 输入绑定赋予了您在地图上添加一分层的能力.
虽然这看起来可能有限,但可以在地图元素内嵌入元素,每个元素都有 [leafletLayer] 输入.
其结果是每层会被添加到地图上.
如果添加一个结构指令 - *ngFor 或者说 *ngIf - 在控制地层时,您可以得到一些额外的灵活性.
<div leaflet style="height: 300px;"
[leafletOptions]="options">
<div *ngFor="let l of layers" [leafletLayer]="l"></div>
</div>
在这个例子中 layers 数组将创建新子 div 键.
每个元素将有一个 [leafletLayer] 输入绑定,将会导致图中加入层.
更多细节,你应该看看 图层和ngFor 演示.
当您使用这种方法控制地层时, 有多个层事件可用 .
图层事件
当你使用 [leafletLayer] 要添加一层,您也可以访问层事件的输出绑定.
目前曝光的两个事件包括: (leafletLayerAdd) 财务报告和审定财务报表 (leafletLayerRemove)。 。 。 .
每一个都发出一个 LeafletEvent 对象.
地图事件
叶取出暴露出许多地图事件,包括地图缩放,地图移动,和鼠标交互. 该插件会曝光多起最常见的事件. 对于其中的每一起事件,事件都是在角地区发射的,所以你不应该做任何额外的工作来让变化的检测工作发挥作用. 例如,请查看演示中的事件部分.
鼠标交互: 叶片 MouseEvent
提供了下列活动:
(leafletClick)(leafletDoubleClick)(leafletMouseDown)(leafletMouseUp)(leafletMouseMove)(leafletMouseOver)(leafletMouseOut)
地图缩放和移动: 叶片事件
提供了下列活动:
(leafletMapMove)(leafletMapMoveStart)(leafletMapMoveEnd)(leafletMapZoom)(leafletMapZoomStart)(leafletMapZoomEnd)
获取地图的引用
有时你可能需要直接访问Leaflet地图实例 .
例如,打电话 invalidateSize() 当显示/隐藏地图时.
实现这一点有几种不同的方法,这取决于你所要做的事情.
最简单和最灵活的方式是使用输出绑定 leafletMapReady。 。 。 .
此输出在地图创建后被引用, 事件的参数是 Map 举个例子.
第二是参考传单指令本身----有几种方法可以做到这一点.
关于指令,你可以援引 getMap() 函数以获取引用 Map 举个例子.
(叶子地图):地图
当地图最初在Leaflet指令内创建时,此输出会释放一次 . 事件只有在地图存在并准备被操纵时才会开火.
<div leaflet
[leafletOptions]="options"
(leafletMapReady)="onMapReady($event)">
</div>
onMapReady(map: Map) {
// Do stuff with map
}
如果你在自己的组件内使用Leaflet指令,这种获取地图的方法最有意义 只需要添加一些有限的功能或者注册一些事件处理器.
向您的组件注入叶片指令
这是比较先进的技术 而且它不会总是工作 取决于你的设置.
特别是,除非您自己编写扩展功能的第三方图书馆,否则这很可能行不通 ngx-leaflet。 。 。 .
如果这种方法对你无效,请尝试使用 leafletMapReady 事件.
在Angular.io中,指令的注入方式与Services相同.
这意味着您可以创建自己的组件或指令并注入 LeafletDirective 进入它.
只有当您的自定义组件/方向存在于相同的 DOM 元素上,并在被注入的Leaflet Directive 后命令使用,或者在孩子的 DOM 元素上命令使用,此操作才会有效 .
<!-- On the same DOM element -->
<div leaflet myCustomDirective>
</div>
<!-- On a child DOM element -->
<div leaflet>
<div myCustomDirective></div>
</div>
@Directive({
selector: '[myCustomDirective]'
})
export class MyCustomDirective {
leafletDirective: LeafletDirective;
constructor(leafletDirective: LeafletDirective) {
this.leafletDirective = leafletDirective;
}
someFunction() {
if (null != this.leafletDirective.getMap()) {
// Do stuff with the map
}
}
}
这种方法的好处是,如果你有兴趣在现有的传单地图指令中添加一些可重复使用的能力,那就有点干净了.
如上所述,它可能不起作用,取决于你如何包装你的部件.
这是如何 @asymmetrik/ngx-leaflet-draw 财务报告和审定财务报表 @asymmetrik/ngx-leaflet-d3 软件包可以工作,因此可以把它们用作参考.
关于更改检测的说明
变化检测是Angular工作方式的核心. Angular.io使用Zone.js来瞄准如何和何时(事件,动作等)来触发变化检测. 仔细观察很重要,因为变化探测可能相当昂贵,所以你不希望它经常发生.
Ngx-leaflet等图书馆必须决定在Angular区内外做什么,平衡方便和性能. Leaflet为很多鼠标事件登记处理器. 为了减轻不断运行更改检测对所有鼠标事件(包括鼠标移动)的性能影响,ngx-leaflet在Angular区外运行了大部分的Leaflet代码. 其影响在于Angular不会自动检测到您在Leaflet事件回调中所做的改变.
解决办法是要么确保在Angular的区内进行角相关改变,要么手动告诉Angular检测变化.
运行在角区内部
Leaflet事件处理器运行于Angular区域外,其中对输入绑定字段的更改不会被自动检测出. 为了保证您的变化被检测和应用,您需要让这些变化在Angular的区域内被改变. 幸运的是,这非常容易.
fitBounds: any = null;
circle = circle([ 46.95, -122 ], { radius: 5000 });
// Inject the Change Detector into your component
constructor(private zone: NgZone) {}
ngOnInit() {
// The 'add' event callback handler happens outside of the Angular zone
this.circle.on('add', () => {
// But, we can run stuff inside of Angular's zone by calling NgZone.run()
// everything inside the arrow function body happens inside of Angular's zone, where changes will be detected
this.zone.run(() => {
this.fitBounds = this.circle.getBounds();
});
});
}
手动触发更改检测
另一个选择是手动告诉更改检测器以检测变化. 这个选项的缺点在于它不太精确. 这将触发对这一组成部分及其所有儿童的改变检测.
fitBounds: any = null;
circle = circle([ 46.95, -122 ], { radius: 5000 });
// Inject the Change Detector into your component
constructor(private changeDetector: ChangeDetectorRef) {}
ngOnInit() {
// The 'add' event callback happens outside of the Angular zone
this.circle.on('add', () => {
// Because we're outside of Angular's zone, this change won't be detected
this.fitBounds = this.circle.getBounds();
// But, it will if we tell Angular to detect changes
this.changeDetector.detectChanges();
});
}
关于标记的说明
如果您在 Angular.io 项目中使用了这个组件, 您的项目使用像 Webpack 这样的捆绑器, 您可能会在地图上遇到使用标记的问题 . 这个问题与Leaflet在使用默认标记图像时如何操纵用于渲染标记的图像URL有关. Url操作是运行时完成的,它以打破URL格式的方式改变URL(无论您使用文件装入器还是URL装入器). 该项目中包含的演示演示展示了如何绕过这个问题(至少在Webpack环境中). 但是,这里粗略地概述了为使它们发挥作用所采取的步骤.
网络包装标记工作
-
导入您的供应商文件中的标记图像, 让 Webpack 处理资产管道中的图像
import 'leaflet/dist/images/marker-shadow.png'; import 'leaflet/dist/images/marker-icon.png'; -
要么静地托管图像,要么使用文件装入器Webpack插件生成图像.
-
确定标记和标记阴影图像的正确URL。 使用文件散列器的,应当能够检查Webpack的输出生成的图像. 如果您是直接服务他们而不散开 只需想出如何解析您服务器上的图像.
-
配置叶片以使用正确的 URL 作为客户标记图像
let layer = marker([ 46.879966, -121.726909 ], { icon: icon({ ...Icon.Default.prototype.options, iconUrl: '2b3e1faf89f94a4835397e7a43b4f77d.png', iconRetinaUrl: '680f69f3c2e6b90c1812a813edf67fd7.png', shadowUrl: 'a0c6cc1401c107b501efee6477816891.png' }) });
角 CLI 标记工作
如果你使用 角 CLI 函数,您可以通过下列方式提供默认的传单标记资产:
-
配置 CLI( 通过编辑)
angular.json列入传单资料如下。 详细指示可见于 资产配置 文档.{ ... "assets": [ "assets", "favicon.ico", { "glob": "**/*", "input": "./node_modules/leaflet/dist/images", "output": "assets/" } ], ... } -
配置叶片以使用正确的 URL 作为客户标记图像
let layer = marker([ 46.879966, -121.726909 ], { icon: icon({ ...Icon.Default.prototype.options, iconUrl: 'assets/marker-icon.png', iconRetinaUrl: 'assets/marker-icon-2x.png', shadowUrl: 'assets/marker-shadow.png' }) });
扩展
有多个库扩展了ngx-leaflet的核心功能:
获取帮助
以下是文章列表、教程、指南和帮助资源:
- 堆叠倒流上的 ngx- 叶
- 高级介绍至@asymmetrik/ngx-leaflet
- 使用@asymmetrik/ngx-leaflet 在角CLI项目
- 将第3党的传单图书馆与@asymmetrik/ngx-leaflet和@angular/cli合并起来
贡献
公关接受。 如果你是BlueHalo的一部分,请在图上贡献 develop 树枝。 如果你在BlueHalo外,请 叉我们的回购做贡献.
许可证
详情见LICENSE.
贷项
传单 是一个很棒的地图包.