leaflet之扩展leaflet类,定制功能
目录
简介:leaflet提供了操作地图的基本类,提供了扩展功能。用户可以自由个性化定制扩展功能,开发自己的插件。
扩展leaflet
Leaflet有几百个插件。这些扩展了Leaflet的功能:有时以通用方式,有时以特定于用例的方式。
有这么多插件的部分原因是Leaflet很容易扩展。本教程将介绍最常用的方法。
请注意,本教程需要已经掌握了以下基础:
- JavaScript
- DOM处理
- 面向对象的编程(理解类,实例,继承,方法和属性等概念)
leaflet架构
让我们看一下Leaflet 1.0.0的简化UML类图。有超过60个JavaScript类,所以图表有点大。幸运的是,我们可以制作一个可缩放的图像L.ImageOverlay:
| 单独查看此示例。 |
从技术角度来看,Leaflet可以以不同的方式扩展:
- 最常见的:创建一个新的子类L.Layer,L.Handler或L.Control与L.Class.extend()
- 移动/缩放地图时图层会移动
- 处理程序是不可见的并解释浏览器事件
- 控件是固定的界面元素
- 在现有类中包含更多功能 L.Class.include()
- 添加新方法和选项
- 改变一些方法
- 使用addInitHook运行额外的构造函数代码。
- 更改现有类的部分(替换类方法的工作方式)L.Class.include()。
本教程介绍了仅在Leaflet 1.0.0中可用的一些类和方法。如果您正在为以前的版本开发插件,请谨慎使用。
L.Class
JavaScript是一种奇怪的语言。它不是一种面向对象的语言,而是一种面向原型的语言。这使得JavaScript在历史上难以在术语的经典OOP含义中使用类继承。
Leaflet通过使用来解决这个问题L.Class,从而简化了类的继承。
尽管现代JavaScript可以使用ES6类,但Leaflet并不是围绕它们设计的。
L.Class.extend()
要在Leaflet中创建任何子类,请使用该.extend()方法。这接受一个参数:具有键值对的普通对象,每个键是属性或方法的名称,每个值是属性的初始值,或方法的实现:
var MyDemoClass = L.Class.extend({
// A property with initial value = 42
myDemoProperty: 42,
// A method
myDemoMethod: function() { return this.myDemoProperty; }
});
var myDemoInstance = new MyDemoClass();
// This will output "42" to the development console
console.log( myDemoInstance.myDemoMethod() );
命名类,方法和属性时,请遵循以下约定:
- 功能,方法,属性和工厂名称应该在lowerCamelCase。
- 班级名称应该在UpperCamelCase。
- 私有属性和方法以下划线(_)开头。这不会使它们变得私密,只是建议开发人员不要直接使用它们。
L.Class.include()
如果已定义类,则可以重新定义现有属性/方法,或者可以使用.include()以下方法添加新属性/方法:
MyDemoClass.include({
// Adding a new property to the class
_myPrivateProperty: 78,
// Redefining a method
myDemoMethod: function() { return this._myPrivateProperty; }
});
var mySecondDemoInstance = new MyDemoClass();
// This will output "78"
console.log( mySecondDemoInstance.myDemoMethod() );
// However, properties and methods from before still exist
// This will output "42"
console.log( mySecondDemoInstance.myDemoProperty );
L.Class.initialize()
在OOP中,类具有构造函数方法。在Leaflet中L.Class,构造函数方法总是被命名initialize。
如果你的类有一些特定的options,那么L.setOptions()在构造函数中初始化它们是个好主意。此实用程序函数将提供的选项与类的默认选项合并。
var MyBoxClass = L.Class.extend({
options: {
width: 1,
height: 1
},
initialize: function(name, options) {
this.name = name;
L.setOptions(this, options);
}
});
var instance = new MyBoxClass('Red', {width: 10});
console.log(instance.name); // Outputs "Red"
console.log(instance.options.width); // Outputs "10"
console.log(instance.options.height); // Outputs "1", the default
Leaflet options以特殊方式处理属性:父类可用的选项将由子类继承:
var MyCubeClass = MyBoxClass.extend({
options: {
depth: 1
}
});
var instance = new MyCubeClass('Blue');
console.log(instance.options.width); // Outputs "1", parent class default
console.log(instance.options.height); // Outputs "1", parent class default
console.log(instance.options.depth); // Outputs "1"
子类运行父的构造函数,然后运行自己的构造函数是很常见的。在传单中,这是使用L.Class.addInitHook()。此方法可用于“挂钩”在类’之后运行的初始化函数,initialize()例如:
MyBoxClass.addInitHook(function(){
this._area = this.options.width * this.options.length;
});
这将在initialize()调用之后运行(调用setOptions())。这意味着this.options存在并且在init钩子运行时有效。
addInitHook 有一个替代语法,它使用方法名称并可以填充方法参数:
MyCubeClass.include({
_calculateVolume: function(arg1, arg2) {
this._volume = this.options.width * this.options.length * this.options.depth;
}
});
MyCubeClass.addInitHook('_calculateVolume', argValue1, argValue2);
父类的方法
调用父类的方法是通过到达父类的原型并使用来实现的Function.call(…)。例如,可以在以下代码中看到L.FeatureGroup:
L.FeatureGroup = L.LayerGroup.extend({
addLayer: function (layer) {
…
L.LayerGroup.prototype.addLayer.call(this, layer);
},
removeLayer: function (layer) {
…
L.LayerGroup.prototype.removeLayer.call(this, layer);
},
…
});
调用父的构造函数是以类似的方式完成的,而是使用ParentClass.prototype.initialize.call(this, …)。
工厂
大多数Leaflet类具有相应的工厂功能。工厂函数与类具有相同的名称,但lowerCamelCase代替UpperCamelCase:
function myBoxClass(name, options) {
return new MyBoxClass(name, options);
}
命名规范
为Leaflet插件命名类时,请遵循以下命名约定:
- 永远不要在插件中公开全局变量。
- 如果您有一个新类,请将其直接放在L命名空间(L.MyPlugin)中。
- 如果继承其中一个现有类,请将其设为子属性(L.TileLayer.Banana)。


