转:另辟渠道的webgis应用开发(附源码)

  在用ARCIMS开发webgis中小型应用程序的时候,我相信很多人和我一样,就是如何将保存在简单数据库(如ACCESS)里的一些专题点信息该如何体现在地图上,这些点多则有3000,4000,另外还可通过地图操作(添加,平移)进行专题点编辑。如果直接用HTML VIEWER,这可是个不大不小的难题。一开始,我们使用了ACETATELAYER方式进行处理,效果不甚理想,在局域网中多用户并发访问时就有明显的速度瓶颈,更何况INTERNET上。
      如下代码就是在此问题上做出的一种解决方案尝试,即部分地图信息客户端化。目前我正在开发,只是部分调试仅在局域网中通过,并没有完全成熟,在线面上还是处理开发阶段。现在介绍一下代码的基本思想,希望大家能够加以讨论。该代码使用JAVASCRIPT开发,它已基础图层地图图片为底图,在此之上进行图层扩展,客户端形成一套小型的webgis,与ARCIMS同步刷新,形成无缝整合,给人感觉就是一个整体的webgis系统。该代码在对象层次关系上模拟ACTIVEX CONNECTOR的重点对象。通过不同refresh函数与基础图层同步更新(为提高客户端速度,开放了很多refresh方式,即只refresh发生改变的对象坐标位置,当然放大缩小平移之类的操作就需要整个客户端refresh,因为每个点都发生了位置变化)。之所以如此层次化,一方面是为了增强代码的可读性和可维护性,另一方面通过封装具体VML代码实现来简化开发过程。这样一来,可以大大减轻服务端的处理,客户端和服务端同时处理,提高地图的运行速度。
    我想重点说明的是,如果将部分地图信息移到客户端,必然需要自主开发一些原本集成好的功能(比如说在FeatureLayer中的WHEREEXPRESSION,BUFFER等功能)用于客户端。以BUFFER为例,圆形如何画,必然是vml的 oval,可以把它作为一个特殊地图图层来看待,它是一个圆,而不是点,线,区(折线),这就是图层类型扩展。同样的道理还用在监控(关于监控的需求可查看 http://www.gisempire.com/bbs/dispbbs.asp?BoardID=23&ID=14998),它是一种特殊的点层,它具体表现内容更丰富,所以也可以把它看成一种图层类型。
    当然,之所以费尽心思放在客户端做,还有个很重要的目的就是为了解决地图特殊信息的可编辑。首先说明,此方法对基础图层的属性是无能为力的,它仅是用于在客户端生成的专题信息。
    以本代码为例,客户端添加一个新点则需要先在相关对象中add,还需要通过数据库的方式将点保存。如果移动某客户端生成点,则显示客户端的移动过程,然后更改该对象的left和top到XY即可。另外要注意的是,客户端gismap对象中的所有涉及点的坐标都是地图坐标,所以经常需要屏幕坐标和地图坐标之间的转换,以前我说过,现在就不多说了,代码也体现比较明显。
     以下是未完成代码的详细内容,以后会将很多实现补充上来,希望给有此需求的人员带来启示,并欢迎大家跟贴讨论,恭请候教。
function GisMap()
{
  var i ;
  this.control = drawonmap ;       //控件名称
  this.visible = true ;          //是否显示
  this.mapXMin = 0 ;          //地图最小X
  this.mapYMin = 0 ;          //地图最小Y
  this.mapXMax = 0 ;          //地图最大X
  this.mapYMax = 0 ;          //地图最大Y
  this.layers = new Layers() ;       //图层集合对象

///返回含屏幕坐标的point对象
  this.fromMapPoint=function(mapX,mapY)
  {
     var point = new PointObject() ;
     point.x = getJX(mapX) ;
     point.y = getWY(mapY) ;
     return point ;
  };
  ///返回含地图坐标的point对象
  this.toMapPoint=function(screenX,screenY)
  {
     var point = new PointObject() ;
     point.x = getScrX(screenX) ;
     point.y = getScrY(screenY) ;
     return point ;
  };
  //获得地图坐标
  function getJX(scrX)
  {
     return (this.mapXMin+parseInt(scrX)/(document.body.clientWidth/(this.mapXMax - this.mapXMin)));  
  }
  function getWY(scrY)
  {
     return (this.mapYMax-parseInt(scrY)/(document.body.clientHeight/(this.mapYMax-this.mapYMin)));
  }
  //获得屏幕坐标
  function getScrX(mapX)
  {
     return (mapX - this.mapXMin) * document.body.clientWidth/(this.mapXMax-this.mapXMin) ;
  }
  function getScrY(mapY)
  {
     return (this.mapYMax - mapY) * document.body.clientHeight/(this.mapYMax-this.mapYMin) ;
  }

  ///画图
  ///在不同环境下可更改此函数的实现
  this.draw=function()
  {
     for (i=1;i<this.layers.count+1;i++)
    {
      this.drawLayer(this.layers.item(i)) ;
      //this.control.innerHTML =  this.stringBuilder.toString() ;
    }
  };

  ///绘制指定层
  this.drawLayer=function(layerObject)
  {
    switch (layerObject.type)
    {
      case "tail" :
         drawTailLayer(layerObject) ;
         break;
      case "denamic" :
        drawDynamicLayer(this.control,layerObject) ;
        break;
     case "point" :
        drawPointLayer(this.control,layerObject) ;
        break;
     case "line" :
        break;
     case "polygon" :
        break;
     }
  };

  //绘制监控层
  function drawTailLayer(layerObject)
  {
     var sHTML ;
     var tailObject = eval("div_tail") ;
     var arr0 ;
     for (i=1;i<layerObject.count+1;i++)
    {
      sHTML = '<div id="' + layerObject.item(i).id + '" name="' + layerObject.item(i).name + '"'  ;
      sHTML+= ' style="position:absolute;z-index:3;left:' + getScrX(layerObject.item(i).x) + ';top:' + getScrY(layerObject.item(i).y) + '">';
      arr0 = layerObject.item(i).content.split(",") ;
      if (arr0.length>0)
      {
        sHTML+= '<table border=0 width=108 bgcolor=#1949A1 cellspacing=1 cellpadding=0 style="font-size:9pt">' ;
        sHTML+= '<tr><td>' ;
        sHTML+= '<table border=0 width="100%" cellspacing=0 cellpadding=0>' ;
        sHTML+= '<tr><td><img src="images/tail/tailtable_top.gif"></td></tr>' ;
        sHTML+= '<tr><td background="images/tail/tailtable_bg.gif">' ;
        sHTML+= '<table border=0 width="100%" cellspacing=0  cellpadding=3>' ;
        for (j=0;j<arr0.length;j++)
        {
           sHTML+= '<tr><td height="20" style="color:white;font-size:9pt">' + arr0[j] + '</td></tr>' ;
        }
        sHTML+= '</table>' ;
        sHTML+= '</td></tr></table>' ;
        sHTML+= '</td></tr></table>' ;
      }
      sHTML+= '</div>' ;
      tailObject.innerHTML+= sHTML ;
    }
  }
  //绘制点层
  function drawPointLayer(parentObject,layerObject)
  {
     var i ;
     var oSB = new StringBuilder()  ;
     if (layerObject.symbol!=null)
     {
          for (i=1;i<=layerObject.count;i++)
         {
             //oSB.append(setPointVML(layerObject.item(i),layerObject.symbol)) ;
             setPointVML(parentObject,layerObject.item(i),layerObject.symbol) ;
         }
     }
     else
     {
            for (i=1;i<=layerObject.count;i++)
           {
                //oSB.append(setPointVML (layerObject.item(i))) ;
                setPointVML (layerObject.item(i)) ;
           }
      }
      return oSB ;
   }
   //绘制线层
   function drawLineLayer(layerObject)
   {
       for (i=0;i<layerObject.count;i++)
      {
         if (layerObject.symbol!=null)
        {
        }
        else
        {
        }
     }
  }
  //绘制区层
  function drawPolygonLayer(layerObject)
  {
      var sHTML ;
      for (i=0;i<layerObject.count;i++)
     {
         if (layerObject.symbol!=null)
        {    
        }
        else
       {
       }
     }
   }
   //绘制动态图层
   function drawDynamicLayer(layerObject)
  {
     var sHTML ;
     sHTML = "" ;
     for (i=0;i<layerObject.count;i++)
    {
        if (layerObject.item(i).type == "point")
       {
       }
       else if (layerObject.item(i).type == "line")
       {
       }
       else if (layerObject.item(i).type == "polygon")
       {
       }
    }
  }

  ///客户端绘图更新
  ///在此处,更新的含义更多体现为更改各要素在屏幕的坐标,即left和top
  this.refresh=function()
  {
     var obj ;
     var i,j ;
     for (i=1;i<this.layers.count+1;i++)
    {
        switch (this.layers.item(i).type)
       {
            case "tail":
                for (j=1;j<this.layers.item(i).count+1;j++)
               {
                     //alert(i + "," + j) ;
                     obj = eval(this.layers.item(i).item(j).id) ;
                    obj.style.left = getScrX(this.layers.item(i).item(j).x) ;
                    //alert(i+"&" + j + ":" + this.layers.item(i).item(j).x + "," + obj.style.left) ;
                    obj.style.top = getScrY(this.layers.item(i).item(j).y) ;
                    //alert(i+"&" + j + ":" + this.layers.item(i).item(j).y + "," + obj.style.top) ;
               }
               break;
            case "point":
               for (j=1;i<this.layers.item(i).count+1;j++)
              {
                    obj = eval(this.layers.item(i).item(j).id) ;
                    obj.style.left = getScrX(this.layers.item(i).item(j).x) ;
                    alert(obj.style.left) ;
                    obj.style.top = getScrY(this.layers.item(i).item(j).y) ;
              }
              break;
           case "" :
       }
    }
  }
//画点对象
function setPointVML(parentObject,pointObject,symbolObject)
{
  var sHTML = "" ;
  switch (symbolObject.style)
  {
   //圆形
   case 0 :
    sHTML+='<v:oval' ;
    if (pointObject.id!="")
     sHTML+= " id=\"" + pointObject.id + "\"";
    if (pointObject.name!="")
     sHTML+= " name=\"" + pointObject.name + "\"";
     sHTML+= ' style="position:relative;' ;
    if (symbolObject.size>0)
    {
     if (pointObject.y!="")
      sHTML+= 'top:' + (parseInt(pointObject.y)+symbolObject.size/2) + ';' ;
     if (pointObject.x!="")
      sHTML+= ' left:' + (parseInt(pointObject.x)+symbolObject.size/2) + ';' ;
     sHTML+= 'width:' + symbolObject.size + ';' ;
     sHTML+= 'height:' + symbolObject.size + ';' ;
    }
    if (symbolObject.color!="")
     sHTML+= ' fillcolor="' +  symbolObject.color + '"';
    if (symbolObject.border>0)
    {
     sHTML+= ' strokeWeight="' + symbolObject.border + '"' ;
     if (symbolObject.bordercolor>0)
      sHTML+= ' strokeColor="' + symbolObject.bordercolor + '"' ;
    }
    sHTML+="></v:oval>" ;
    break;
   //矩形
   case 1 :
    sHTML+='<v:rect ' ;
    if (pointObject.id!="")
     sHTML+= " id=\"" + pointObject.id + "\"";
    if (pointObject.name!="")
     sHTML+= " id=\"" + pointObject.name + "\"";
     sHTML+= ' style="position:relative;' ;
    if (symbolObject.size>0)
    {
     if (pointObject.y!="")
     {
      sHTML+= 'top:' + String(parseInt(pointObject.y)+symbolObject.size/2) + ';' ;
     }
     if (pointObject.x!="")
      sHTML+= ' left:' + (parseInt(pointObject.x)+parseInt(symbolObject.size/2)) + ';' ;
     sHTML+= 'width:' + symbolObject.size + ';' ;
     sHTML+= 'height:' + symbolObject.size + ';' ;
    }
    if (pointObject.color!="")
     sHTML+= ' fillcolor="' +  symbolObject.color + '"';
    if (pointObject.border>0)
    {
     sHTML+= ' strokeWeight="' + symbolObject.border + '"' ;
     if (symbolObject.bordercolor>0)
      sHTML+= ' strokeColor="' + symbolObject.bordercolor + '"' ;
    }
    sHTML+="></v:rect>" ;
    break;
   //图片
   case 10 :
    sHTML+='<v:image ' ;
    if (pointObject.id!="")
     sHTML+= " id=\"" + pointObject.id + "\"" ;
    if (pointObject.name!="")
     sHTML+= " id=\"" + pointObject.name + "\"" ;
    if (symbolObject.image!="")
    {
     sHTML+= ' src="' + symbolObject.image + '"' ;
     sHTML+=' style="top:' + pointObject.y + ';left:' + pointObject.x + '"' ;
    }
    sHTML+= "></v:image>" ;
    break;
  }
  var newPoint = document.createElement(sHTML) ;
  parentObject.insertBefore(newPoint) ;
}
}

///layers集合
function Layers()
{
var pri_LayerArray = new Array() ;
this.count=pri_LayerArray.length ;
this.item=function(index)
{
  return pri_LayerArray[index-1] ;
};
this.add=function(layer)
{
  pri_LayerArray[pri_LayerArray.length] = layer ;
  this.count=pri_LayerArray.length ;
};
this.remove=function(index)
{
  var i ;
  for (i=index;i<pri_LayerArray.length;i++)
  {
   pri_LayerArray[index-1] = pri_LayerArray[index] ;
  }
  pri_LayerArray[pri_LayerArray.length-1] = null ;
  this.count=pri_LayerArray.length ;
}
}

///自我约束的layer模式,点线面图层需谨慎使用
///使用错误则不能自我判别
function LayerObject(layerid,layername)
{
var pri_objArray =new Array();
this.id = layerid ;
this.name = layername ;
this.visible = true ;
this.type = "dynamic" ;
this.symbol = null ;
this.count = pri_objArray.length ;
this.add=function(object)
{
  pri_objArray[pri_objArray.length] = object ;
  this.count = pri_objArray.length ;
} ;
this.item = function(index)
{
  return pri_objArray[index-1] ;
}
this.remove=function(index)
{
  for (i=index;i<this.count;i++)
  {
   pri_objArray[index-1] = pri_objArray[index] ;
  }
  pri_objArray[pri_objArray.length-1] = null ;
  this.count = pri_objArray.length ;
}
this.setSymbol=function(object)
{
  if (this.type == "dynamic")
  {
   return null ;
  }
  else
  {
   this.symbol = object ; //symbol赋值
  }
}
}

//PolyLine对象
function PolyLineObject()
{
var pri_PolyLine = null;
var pri_Stroke = null ;
this.parent = null ;
this.id = "" ;
this.Points = new Points() ;
this.filled = "false" ;
this.startArrow = "" ;
this.endArrow = "" ;
this.dashStyle = "" ;
}
//点集合
function Points()
{
var pri_Points = new Array() ;
this.count = pri_Points.length ;
this.item=function(index)
{
  return p_Points[index-1] ;
};
this.add=function(pointObject)
{
  p_Points[p_Points.length] = pointObject ;
  this.count = getLength() ;
  
};
this.remove=function(index)
{
  var i ;
  for (i=index;i<this.count;i++)
  {
   pri_Points[index-1] = pri_Points[index]
  }
  pri_Points[pri_Points.length-1] = null ;
  this.count = getLength() ;
}
function getLength()
{
  return p_Points.length ;
}
}

//线对象
function LineObject()
{
var line = null ;
this.parent = null ;
this.id = "" ;
this.fromX = 0 ;
this.fromY = 0 ;
this.toX = 0 ;
this.toY = 0 ;
this.symbol = new LineSymbol() ;
}

//点对象
function PointObject(id,name,code,x,y)
{
this.id = id ;
this.name = name ;
this.code = code ;
this.x = x ;
this.y = y ;
this.symbol = null ;
}

//监控对象
function TailObject()
{
this.id = "" ;
this.id = "" ;
this.x = "" ;
this.y = "" ;
this.content = "" ;
}

///范围
function Envelope(xmin,ymin,xmax,ymax)
{
this.xMin = xmin ;
this.yMin = ymin ;
this.xMax = xmax ;
this.yMax = ymax ;
}

function PointSymbol()
{
this.style=0 ;
this.size=10 ;
this.border=0 ;
this.color = "red" ;
this.bordercolor="" ;
this.transparency = 1 ;
this.image="" ;   //如果style=image,给这个属性赋值(相对路径)
}

//字符串连接操作类,大量字符串累加的时候可提高效率
function StringBuilder(sString)
{

this.length=0;
this._current=0;
this._parts=[];
this._string=null;
if(sString!=null)
this.append(sString);

this.append=function(sString)
{  
   this.length+=(this._parts[this._current++]=String(sString)).length;
   this._string=null;
   return this;
}
this.appendSB = function(stringBuilder)
{
   //for (i=0;i<stringBuilder.length;i++)
   //{
   // this.append(String(stringBuilder._parts[i])) ;
   //}
   this.append(stringBuilder.toString()) ;
   return this ;
}
this.toString=function()
{
   if(this._string!=null)
       return this._string;
   var s=this._parts.join("");
   this._parts=[s];
   this._current=1;
   return this._string=s;
}
}

 

你可能感兴趣的:(Web)