当整合第三方库的时候,我们通常需要配置和初始化库来与我们的需求相配。对于我们的例子,在重载'afterRender'方法时,我们将操作Leaflet的初始化。这个方法的运行发生在,我们定制的组件已经被渲染到DOM并准备开始交互的时候 。我们同样添加一个类别名并为我们的地图引用配置变量。
Ext.define('Ext.ux.LeafletMapView', {
extend: 'Ext.Component',
alias: 'widget.leafletmapview',
config:{
map: null
},
afterRender: function(t, eOpts){
this.callParent(arguments);
var leafletRef = window.L;
if (leafletRef == null){
this.update('No leaflet library loaded');
} else {
var map = L.map(this.getId());
map.setView([42.3583, -71.0603], 13);
this.setMap(map);
L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
key: 'YOUR_API_KEY',
styleId: 997,
maxZoom: 18
}).addTo(map);
}
}
});
单步进入 ‘afterRender’ :
var leafletRef = window.L;
if (leafletRef == null){
this.update('No leaflet library loaded');
} else {
....
}
我们尝试访问加载在window.L命名空间的Leaflet库。如果我们不能获得库的引用,我们将更新组件的html文件,显示一则声明存在加载库文件错误的消息。
var map = L.map(this.getId());
在这里我们创建一个Leaflet地图对象,把Ext JS组件的ID号传递过去。缺省情况下,HTML的标签由Ext创建。 组件将会变为一个div,这是Leaflet初始化地图控件要求做到的。相比硬编码一个ID给div的引用,我们将使用Ext框架在渲染控件时生成的ID号。这允许我们在application.map.setView([42.3583, -71.0603], 13)函数调用上拥有多个控件的实例。
这一步就把地图的纬度/经度设置为麻省州波士顿的位置,并设置放大级别为13。对于不同的locations.this.setMap(map)的函数调用,还有很多的在线工具供查阅纬度和经度。
|
L.tileLayer('http://{s}.tile.cloudmade.com/{key}/{styleId}/256/{z}/{x}/{y}.png', {
key: 'YOUR_API_KEY',
styleId: 997,
maxZoom: 18
}).addTo(map);
这将会配置Leaflet时用CloudMade的地图配置文件。假设你创建一个账号并注册你的应用程序,你将获得一个API密钥,这个密钥是你要在‘YOUR_API_KEY’里要提供的。不要担心迷惑性的URL网址,这是当你移动地图时,Leaflet将怎样动态加载你的配置文件。我建议你去看一看Leaflet API文档。
|
此时此刻,你有一个基本的地图控件可以在你的应用中使用。然而,我们完全没有这样做。如果你按照现状来使用,你不会看见你所期待的。尺寸和你的布局不搭配。Leaflet需要我们去调用一个叫做'invalidateSize()'这个方法在每次地图尺寸发生变化的时候,然后Leaflet就会渲染那个尺寸。这在我们的封装组件中是个很容易解决的问题。我们可以重载'onResize'方法,这个方法会在布局中尺寸发生改变时调用,并在地图中调用'invalidteSize'方法。
我们要把如下代码添加到我们的控件中:
onResize: function(w, h, oW, oH){
this.callParent(arguments);
var map = this.getMap();
if (map){
map.invalidateSize();
}
}
这将会在布局发生改变时被调用,如果我们有一个合法的地图引用,那么我们将看到这一点。如果没有,我们将通过‘invalidateSize’通知Leaflet。
现在我们可以在布局中使用组件,你可以看到它会响应我们提供给它的布局维度。如果布局因为浏览器尺寸改变或者滑动而改变,你将会看到新尺寸会被应用。在我们定制的封装组件,我们用了行数不多的代码,是第三方库Leaflet控件完美地搭载Ext JS布局系统。
|
使用示例
我们使用这个新的封装组件,来建立一个简单的Ext JS应用。
Ext.Loader.setConfig({
enabled: true,
paths:{
'Ext.ux':'ux'
}
});
Ext.require(['Ext.ux.LeafletMapView']);
Ext.onReady(function() {
Ext.create('Ext.container.Viewport', {
layout: 'vbox',
items: [
{
xtype: 'leafletmapview',
flex: 1,
width: '100%'
}
]
})
});
这将创建一个使用浏览器全屏的viewport,并使用全景渲染我们的地图。你使用一些简单的缩放控件,将会看到一个较大的波士顿地区的地图。
下一步要做的就是操作地图和外部控件的交互。我们在地图上添加一个按钮,在它被点击的时候让地图缩放到一个位置。根据Leaflet文档,你需要做的就是在地图对象上调用'setView',并传递经纬度的坐标数组和缩放级别。我们要用我们的封装组件在我们创建的'afterRender'函数中显示暴露地图对象,然后使这个按钮能够被对象和调用在之上的方法所访问。
|
在视区项目数组中把这个控件放到我们地图控件之上:
{
xtype: 'button',
text: 'Show Buffalo',
listeners:{
click: function(){
var map = Ext.ComponentQuery.query("viewport leafletmapview")[0];
map.getMap().setView([42.8864, -78.8786], 13);
}
}
}
以上代码将会显示一个按钮。当它被点击的时候,代码将会获得一个对地图对象的引用,并更新它的视窗到新的位置。有很多方法引用一个在Ext JS应用程序中的组件,包括Controler refs,Ext.ComponentQuery()等等。在这个例子中,为了方便,我们将使用一个组件查询来找到在视窗中的地图组件。一旦我们获得了那个引用,我们可以调用'getMap'来获取Leaflet地图实例并在其上直接调用任何Leaflet的API函数。
|
此后,你可以让你的组件变得巧妙无比。你能为所有必需的启动参数添加配置属性,你就能定制每一个使用Ext Js配置参数的实例,而不是第三方库的传统做法。你可以添加新的属性来切换库特性。举个例子,你可以添加一个属性来启用Leaflet的定位功能,这将会试图调用你浏览器的地理API来查找你的位置。你可以我的GitHub上,看到更加复杂的例子(仓库地址)
结论
所有的库都不同,并可能会带来附加的挑战,但是这个概念将会帮助你让你的Ext JS或者Sencha Touch应用集整合到一起。在Sencha市场和GitHub已经有很多的封装组件可以获得,所以你可能不需要自己创建。但是如果没有一个你所需要的库,你现在就知道如何创建你自己的库并把它分享给其他Sencha社区的其他开发者。
|
|
|
|
|