在介绍动态标注前先介绍一个KML.它是GOOGLE EARTH的接口标准,后来被广泛应用,在行业里大家都遵循这个标准.这里查看 KML说明.
MAPEASY给出了象地图填加标注的方法.这段:
var marker = new Marker(coord.getPoint(), Marker.LARGE);
alert(coord.x/1e16+ ":"+coord.y/1e16);
map.addOverlay(marker);
marker.setInfo( "Hello! it's marker: <a href=\"http://www.3snews.net/\" target=\"_blank\">#" + marker.getId() + "</a>");
但相对较简单,我们怎样把它封装成自己的组件呢
总体思路:利用任意页面从库里读取数据------>组织成KML格式输出到页面------>利用AJAX方法读到KML内容并解析-------->通过同步或异步的方式动态添加标注.
1. 建一个用来组织KML文档的基类.包含KML的所有节点属性.(目前只解析了标注部分)
/**
* 解析xml的基类
*---------by zygao-----------
*
*/
function Folder()
{
//文件夹名称
this.name;
//默认节点是否打开(0-1)
this.open = 1;
//存储Placemark对象的ArrayList
this.placemarkList;
this.getFolderName = function()
{
return this.name;
}
this.setFolderName = function(name)
{
this.name = name;
}
this.getOpen = function()
{
return this.open;
}
this.setOpen = function(open)
{
this.open = open;
}
this.getPlacemarkListCount = function()
{
return this.placemarkList.size();
}
this.clearPlacemarkList = function()
{
this.placemarkList.remove();
}
this.createPlacemarkList = function()
{
this.placemarkList = new ArrayList();
}
this.addPlacemark = function(placemark)
{
this.placemarkList.add(placemark);
}
}
/**
* 解析xml的基类
*---------by zygao-----------
*
*/
function Placemark()
{
//标注的名称
this.name = '';
//点坐标信息(x,y,h)
this.coordinates = '';
//默认描述信息
this.description =' ';
//标注的缩放级别
this.scale = 1.0;
//标注的url
this.href = '';
//标注的高
this.h = 0;
//标注的宽
this.w = 0;
//阴影标注的url
this.shadowhref = '';
//阴影标注的高
this.shadowh = 0;
//阴影标注的宽
this.shadoww = 0;
this.getPlacemarkName= function()
{
return this.name;
}
this.getCoordinates= function()
{
return this.coordinates;
}
this.getDescription= function()
{
return this.description;
}
this.getScale= function()
{
return this.scale;
}
this.getHref= function()
{
return this.href;
}
this.getH= function()
{
if( this.scale)
{
return this.h* this.scale;
}
else
{
return this.h;
}
}
this.getW= function()
{
if( this.scale)
{
return this.w* this.scale;
}
else
{
return this.w;
}
}
this.getShadowHref= function()
{
return this.shadowhref;
}
this.getShadowH= function()
{
if( this.scale)
{
return this.shadowh* this.scale;
}
else
{
return this.shadowh;
}
}
this.getShadowW= function()
{
if( this.scale)
{
return this.shadoww* this.scale;
}
else
{
return this.shadoww;
}
}
this.setName = function(name)
{
this.name = name;
}
this.setDescription = function(description)
{
this.description = description;
}
this.setCoordinates = function(coordinates)
{
this.coordinates = coordinates;
}
this.setScale = function(scale)
{
if(scale=='')
{
this.scale = 1.0;
}
else
{
this.scale = scale;
}
}
this.setHref = function(href)
{
if(href=='')
{
this.href = imgBaseDir + "marker_large.png";
}
else
{
this.href = href;
}
}
this.setH = function(h)
{
if(h=='')
{
this.h = 34;
}
else
{
this.h = h;
}
}
this.setW = function(w)
{
if(w=='')
{
this.w = 20;
}
else
{
this.w = w;
}
}
this.setShadowHref = function(shadowhref)
{
if(shadowhref==''||shadowhref== null)
{
this.shadowhref = imgBaseDir + "marker_large_shadow.png";
}
else
{
this.shadowhref = shadowhref;
}
}
this.setShadowH = function(shadowh)
{
if(shadowh==''||shadowh== null)
{
this.shadowh = 37;
}
else
{
this.shadowh = shadowh;
}
}
this.setShadowW = function(shadoww)
{
if(shadoww==''||shadoww== null)
{
this.shadoww = 34;
}
else
{
this.shadoww = shadoww;
}
}
}
这里定义了两个类,一个是Folder,一个是Placemark.
对这两个类有什么不明白的地方可以参考 KML说明
有了这个类我们就可以方便的读取KML的节点属性,而且对于新的节点我们只需要添加新的基类就行了.
2. 定义一个AJAX类用来解析KML.
/**
* 地图数据控制接口
*---------by zygao-----------
* 利用ArrayList存储kml数据
*/
function AjaxXml(model) {
this.xml;
this.folderList = new ArrayList();
//this.model = model;
this.getFolderList = function()
{
return this.folderList;
}
this.getXml = function()
{
return this.xml;
}
/*
* 读取xml串
* 参数1 输出流的地址
* 参数2 是否异步 true=异步,false=同步
*/
this.createXml = function(url,bool,markerType)
{
var arr = url.split('.');
var ext = arr[arr.length-1];
if (ext == "kml" || ext == "xml")
{
this.dissolutionXml(url);
}
else
{
//------------------------异步调用读取xml
if(bool== true)
{
var xmlObj = null;
if(window.XMLHttpRequest){
xmlObj = new XMLHttpRequest();
} else if(window.ActiveXObject){
xmlObj = new ActiveXObject( "Microsoft.XMLHTTP");
} else {
return;
}
xmlObj.onreadystatechange = function()
{
if(xmlObj.readyState == 4)
{
this.xml = xmlObj.ResponseText;
dissolutionXml(markerType);
}
}
xmlObj.open ('get', url, true);
xmlObj.send ('');
}
else
{
//------------------------同步调用读取xml
var xmlObj = null;
if(window.XMLHttpRequest){
xmlObj = new XMLHttpRequest();
} else if(window.ActiveXObject){
xmlObj = new ActiveXObject( "Microsoft.XMLHTTP");
} else {
return;
}
xmlObj.open ('get', url, false);
xmlObj.send ('');
//XMLObj = xmlObj.ResponseXML;
strResult = xmlObj.ResponseText;
this.xml = strResult;
this.dissolutionXml();
}
}
}
/*
* 解析xml----同步
*/
this.dissolutionXml = function(url)
{
var XMLResult = new ActiveXObject( "Microsoft.XMLDOM");
XMLResult.async = false;
if(url)XMLResult.load(url); else XMLResult.loadXML( this.xml);
var folders = XMLResult.selectNodes( "/kml/Document/Folder");
if(folders)
{
for( var i=0;i<folders.length;i++)
{
var folder = new Folder();
var _foldername = folders[i].selectSingleNode( "name");
var _open = folders[i].selectSingleNode( "open");
folder.setFolderName(_foldername.text);
folder.setOpen(_open.text);
var placemarks = folders[i].selectNodes( "Placemark");
if(placemarks)
{
folder.createPlacemarkList();
for( var j=0;j<placemarks.length;j++)
{
var placemark = new Placemark();
var nodelist = placemarks[j].childNodes;
var _placemarkname = placemarks[j].selectSingleNode( "name");
var _description = placemarks[j].selectSingleNode( "description");
var _coordinates = placemarks[j].selectSingleNode( "Point/coordinates");
placemark.setName(_placemarkname.text);
placemark.setDescription(_description.text);
placemark.setCoordinates(_coordinates.text);
var _iconstyle = placemarks[j].selectSingleNode( "Style/IconStyle");
if(_iconstyle)
{
var _scale = placemarks[j].selectSingleNode( "Style/IconStyle/scale");
if(_scale) placemark.setScale(_scale.text);
var _href = placemarks[j].selectSingleNode( "Style/IconStyle/Icon/href");
if(_href) placemark.setHref(_href.text);
var _h = placemarks[j].selectSingleNode( "Style/IconStyle/Icon/h");
if(_h) placemark.setH(_h.text);
var _w = placemarks[j].selectSingleNode( "Style/IconStyle/Icon/w");
if(_w) placemark.setW(_w.text);
var _shadowicon = placemarks[j].selectSingleNode( "Style/IconStyle/ShadowIcon");
if(_shadowicon)
{
var _shadowhref = placemarks[j].selectSingleNode( "Style/IconStyle/ShadowIcon/href");
if(_shadowhref) placemark.setShadowHref(_shadowhref.text);
var _shadowh = placemarks[j].selectSingleNode( "Style/IconStyle/ShadowIcon/h");
if(_shadowh) placemark.setShadowH(_shadowh.text);
var _shadoww = placemarks[j].selectSingleNode( "Style/IconStyle/ShadowIcon/w");
if(_shadoww) placemark.setShadowW(_shadoww.text);
}
else
{
placemark.setShadowHref('');
placemark.setShadowH('');
placemark.setShadowW('');
}
}
else
{
placemark.setScale('');
placemark.setHref('');
placemark.setH('');
placemark.setW('');
placemark.setShadowHref('');
placemark.setShadowH('');
placemark.setShadowW('');
}
folder.addPlacemark(placemark);
} //end for
} //end if(placemarks)
this.folderList.add(folder);
} //end for
} //end if(folders)
}
/*
* 解析xml----一异步
*/
function dissolutionXml(markerType)
{
var folderList = new ArrayList();
var XMLResult = new ActiveXObject( "Microsoft.XMLDOM");
//1.服务器端必须设置DOM设为同步模式加载数据 xmldoc.async=false
//2.load远程数据时,必须设置为:ServerHTTPRequest xmldoc.setProperty "ServerHTTPRequest",true
XMLResult.async = false;
XMLResult.loadXML( this.xml);
var folders = XMLResult.selectNodes( "/kml/Document/Folder");
if(folders)
{
for( var i=0;i<folders.length;i++)
{
var folder = new Folder();
var _foldername = folders[i].selectSingleNode( "//name");
var _open = folders[i].selectSingleNode("//open");
folder.setFolderName(_foldername.text);
folder.setOpen(_open.text);
var placemarks = folders[i].selectNodes("//Placemark");
if(placemarks)
{
folder.createPlacemarkList();
for(var j=0;j<placemarks.length;j++)
{
var placemark = new Placemark();
var nodelist = placemarks[j].childNodes;
var _placemarkname = placemarks[j].selectSingleNode("name");
var _description = placemarks[j].selectSingleNode("description");
var _coordinates = placemarks[j].selectSingleNode("Point/coordinates");
placemark.setName(_placemarkname.text);
placemark.setDescription(_description.text);
placemark.setCoordinates(_coordinates.text);
var _iconstyle = placemarks[j].selectSingleNode("Style/IconStyle");
if(_iconstyle)
{
var _scale = placemarks[j].selectSingleNode("Style/IconStyle/scale");
if(_scale) placemark.setScale(_scale.text);
var _href = placemarks[j].selectSingleNode("Style/IconStyle/Icon/href");
if(_href) placemark.setHref(_href.text);
var _h = placemarks[j].selectSingleNode("Style/IconStyle/Icon/h");
if(_h) placemark.setH(_h.text);
var _w = placemarks[j].selectSingleNode("Style/IconStyle/Icon/w");
if(_w) placemark.setW(_w.text);
var _shadowicon = placemarks[j].selectSingleNode("Style/IconStyle/ShadowIcon");
if(_shadowicon)
{
var _shadowhref = placemarks[j].selectSingleNode("Style/IconStyle/ShadowIcon/href");
if(_shadowhref) placemark.setShadowHref(_shadowhref.text);
var _shadowh = placemarks[j].selectSingleNode("Style/IconStyle/ShadowIcon/h");
if(_shadowh) placemark.setShadowH(_shadowh.text);
var _shadoww = placemarks[j].selectSingleNode("Style/IconStyle/ShadowIcon/w");
if(_shadoww) placemark.setShadowW(_shadoww.text);
}
else
{
placemark.setShadowHref('');
placemark.setShadowH('');
placemark.setShadowW('');
}
}
else
{
placemark.setScale('');
placemark.setHref('');
placemark.setH('');
placemark.setW('');
placemark.setShadowHref('');
placemark.setShadowH('');
placemark.setShadowW('');
}
folder.addPlacemark(placemark);
}//end for
}//end if(placemarks)
folderList.add(folder);
}//end for
}//end if(folders)
addObject(folderList,markerType);
}
/*
* 加标注----一异步
*/
function addObject(folderList,markerType)
{
//利用ArrayList存储得到的标注
if(folderList)
{
for(var i=0;i<folderList.size();i++)
{
var foldername = folderList.get(i).getFolderName();
var placemarkListCount = folderList.get(i).getPlacemarkListCount();
var placemarkList = folderList.get(i).placemarkList;
for(var i=0;i<placemarkListCount;i++)
{
var placemark = placemarkList.get(i);
var point = new Point(placemark.getCoordinates().split(',')[0],placemark.getCoordinates().split(',')[1]);
var icon = new Icon(placemark.getW(), placemark.getH(), placemark.getHref());
var shadowicon = new Icon(placemark.getShadowW(), placemark.getShadowH(), placemark.getShadowHref());
Marker.TEST = new Array(icon,shadowicon);
var marker = new Marker(point, Marker.TEST,markerType);
marker.setInfo(placemark.getDescription());
model.addOverlay(marker);
}
}
}
}
//alert("text:"+item.text);
//alert("nodename:"+item.attributes[0].name+" nadevalue:"+item.attributes[0].value);
}
这个类做了两件事.
一是读取KML文档的内容并解析.
二是在异步读取的同时添加标注.
这里用到了一个叫ArrayList的类.把它理解成我们C#中的ArrayList就行了.
AjaxXml类中包含了一个createXml方法,实际上就是一个AJAX的封装.很多JS框架都实现了,这里就不多解释了.
dissolutionXml方法用来解析KML节点数据(标注相关信息),并将内容通过之前定义的两个基类存放在ArrayList里.
3. 建一个用来创建标注个类(这个类用来统一接口,不管前两个类怎么写的,只管调用就好了)
/*
* 创建标注类
* --------by zygao-----------
*
*/
function CreateObject(model)
{
this.model = model;
this.addObject = function(url,markerType)
{
//利用ArrayList存储得到的标注
var ajaxXml = new AjaxXml(model);
//将页面地址或.xml文件地址发送到ajaxXml类处理
if( url!="" ) ajaxXml.createXml(url, true,markerType);
//同步---得到返回的ArrayList
var folderList = ajaxXml.getFolderList();
if(folderList)
{
for( var i=0;i<folderList.size();i++)
{
var folder = folderList.get(i);
var foldername = folder.getFolderName();
var placemarkListCount = folder.getPlacemarkListCount();
var placemarkList = folder.placemarkList;
for( var j=0;j<placemarkListCount;j++)
{
//加标注
var placemark = placemarkList.get(j);
var point = new Point(placemark.getCoordinates().split(',')[0],placemark.getCoordinates().split(',')[1]);
var icon = new Icon(placemark.getW(), placemark.getH(), placemark.getHref());
var shadowicon = new Icon(placemark.getShadowW(), placemark.getShadowH(), placemark.getShadowHref());
Marker.TEST = new Array(icon,shadowicon);
var marker = new Marker(point, Marker.TEST,markerType);
marker.setInfo(placemark.getDescription());
this.model.addOverlay(marker);
}
}
}
}
this.addRandomObject = function(count,markerType)
{
var viewerBound = this.model.getZoom().getViewerBound();
var hight = viewerBound.getHeight()/1e16;
var width = viewerBound.getWidth()/1e16;
var minx = viewerBound.getMinX()/1e16;
var miny = viewerBound.getMinY()/1e16;
//var arrList = new ArrayList();
for ( var i = 0; i < count; i++)
{
var point = new Point(minx+width*Math.random(),miny+hight* Math.random());
this.model.addOverlay( this.addRandomMarker(point, i ,markerType));
}
}
this.addRandomMarker = function(point, index,markerType)
{
var letter = String.fromCharCode( "A".charCodeAt(0) + index);
var icon = new Icon(20, 34, "http://ditu.google.com/mapfiles/marker" + letter + ".png");
var shadowicon = new Icon(37, 34, "http://ditu.google.com/mapfiles/shadow50.png");
Marker.GOOGLE = new Array(icon,shadowicon);
var marker = new Marker(point, Marker.GOOGLE,markerType);
marker.setInfo("标注 :<b>" + letter + "</b>");
//MapEvent.addListener(marker, MapEvent.MOVESTART, function() { debugger; hideInfoWindown(infoWindowID); });
//MapEvent.addListener(marker, MapEvent.MOVEEND, function() { showInfoWindow(mapModel, marker); });
return marker;
}
}
下面介绍怎么用此组件.
第一步:将AjaxXml文件夹和ArrayList.js类文件拷贝到项目里,并包含里面的类文件(方法参照之前的开发体会二).再将XML文件夹拷贝到项目里(这里的XML文件夹仅为测试用,实际应用中KML文档都是通过页面形式输出).
第二步:找到MapBuilder,添加
include(baseDir + "/ArrayList.js");
include(baseDir + "/AjaxXml/AjaxXml.js");
include(baseDir + "/AjaxXml/BaseXml.js");
include(baseDir + "/AjaxXml/CreateObject.js");
和
/**
* 填加扩展工具
*
* @param para 扩展工具别名
*/
this.addTool = function(para) {
if (para == MapBuilder.TOOL_SLIDERBAR) {
new SliderWidget( this.mapModel).paint();
}
if (para == MapBuilder.TOOL_MAPTYPE) {
new MapTypeWidget( this.mapModel).paint();
}
}
//--------by zygao-------
this.addObject = function(url)
{
new CreateObject(this.mapModel).addObject(url,'load');
}
this.addRandomObject = function(count)
{
new CreateObject(this.mapModel).addRandomObject(count,'load');
}
//--------by zygao-------
/**
* 获得地图对象
*/
this.getMap = function() {
return this.mapModel;
}
第三步:找到demo.html
MapServiceURL = 'xml/Xq_arcims_xml.xml';
//----by zygao------ 地图标注
mapbuilder.addObject(MapServiceURL);
//----by zygao------ 随机地图标注(测试)
mapbuilder.addRandomObject(26);
最后运行一下试试吧.