arcgis总结——结合SVG制作轨迹回放

     轨迹回放有几个方案:

     方案一、调用arcgis自己的api,设置定时器,一段时间清空当前点,绘制下一个点。

                     缺点:点的移动不是连续的,一闪一闪的,而且速度不均匀

     方案二、利用HTML5的canvas,原理和上面一样

                      缺点:同上

     方案三、利用SVG制作动画

                      没有缺点,非常完美


      通过比较,最后使用SVG进行制作轨迹回放。

      这里有几个难点:

      1、屏幕坐标和经纬度的同步

      2、SVG动画层会遮盖地图层的事件

      3、由于是连续动画,移动到某时刻并不一定在路径数组的点上,暂停和漫游需要知道回放到的路基数组的具体区间

    

     实现的思路:

     1、启动的时候,动态把SVG的路径解析出来

     2、设置定时器,频率要比播放速度快,尽量快就好了。

           定时器里面做两个事情:a、判断是否到达下一个点,把数组偏移量记录下来。b、判断是否碰到屏幕边界,屏幕边界需要漫游。

           当然,这个定时器只有在播放的时候触发逻辑。

     3、zoomin和zoomout,漫游的时候删除原来SVG动画,通过第二步的数组偏移量,把后续的路径按照新的屏幕坐标解析出来。当前轨迹点也同理重新绘制

     4、屏幕坐标和经纬度的同步可以通过arcgis api里面的方法进行

     5、事件被遮盖的问题,SVG提供了一种方式,通过embed 的wmode="opaque"设置可以解决。但是我这里的SVG如果潜入到embed中,则不方便动态获取DOM,也就不好实现SVG的重绘。因此排除掉此方法。

           考虑到被遮盖的事件只有鼠标点击和滚轮的zoomin和zoomout,鼠标拖动的漫游。而且希望在播放状态的漫游中会自动适配到轨迹,暂停和停止不做限制,因此考虑自己来实现arcgis的以上事件。

     6、鼠标点击和滚轮的zoomin和zoomout的事件通过SVG的鼠标点击事件,事件中直接调用arcgis的api即可。由于SVG没有鼠标拖拽事件,则需要独立实现,把移动的方向获取,然后调用arcgis的api即可。

     下面看一下关键代码

     核心对象:

    

//track用来存储轨迹状态,动态获得播放当前状态
var track={
      //轨迹的初始经纬度,一旦获得则不能被改变
      originalLon:[],
      originalLat:[],
      //未播放的路径经纬度
      lon:[],
      lat:[],
      //屏幕坐标
      x:[],
      y:[],
      //当前播放点的经纬度
      now:[],
      //当前播放点的屏幕坐标
      nowXY:[],
      //轨迹长度
      length:0,
      //当前数组偏移量
      i:0,
      //屏幕边界点坐标
      limitXY:[],
      //设置当前数组偏移量和判断是否碰壁,碰壁则漫游
      nowTimer:setInterval(function(){
           if(!document)
               return;
           //设置当前数组偏移量
           if(track.lon[track.i]-track.now()<0.0001 && track.lat[track.i]-track.now[1]<0.0001){
              if(processManager.isStart)
                 track.i++;
           //判断是否碰壁,碰壁则漫游
           if(track.nowXY[0]>=track.limitXY[0] || track.nowXY[1]>=track.limitXY[1] || 
              track.nowXY[0]<=0 || track.nowXY[1]<=0){
              if(processManager.isStart){
                 var point=new esri.geometry.Point({
                     x:track.now[0],
                     y:track.now[1]
                 });
                 map.centerAt(point);
              } 
           }
      },50)
)};

//processManager对象用来存储播放状态
var processManager={isStart:false};

//SVGEvent类用来实现SVG的扩展事件
var SVGEvent=function(){
  ...
}

//用静态方法来实现事件绑定
SVGEvent.bindEvent=function(element,eventName,fn){
   if(!element || element=="svg")
       element=window;
   //鼠标滚动事件
   if(eventName=="mousewheel"){
      window.onmousewheel=document.onmousewheel=fn;
   }
   //鼠标拖动事件
   if(eventName=="mouseDrag"){
      var state=false,original_x,original_y;
      element.οnmοusedοwn=function(event){
         original_x=e.clientX;
         original_y=e.clientY;
         state=true;
      };
      element.οnmοusemοve=function(event){
         if(state){
            var e=event ? event : window.event;
         }
      };
      element.οnmοuseup=function(event){
         if(state){
            state=false;
            var diffX=parseInt(event.clientX-original_x);
            var diffY=parseInt(event.clientY-original_y);         
            var dx="center";
            var dy="center";
            var d="center";
            if(Math.abs(diffX)>80)
               dx=diffX>0 ? "right" : "left";
            if(Math.abs(diffY)>80)
               dy=diffY>0 ? "down" : "up";
            if(dx!="center" && dy!="center")
               d=dx+dy;
            if(dx!="center" && dy=="center")
               d=dx;
            if(dx=="center" && dy!="center")
               d=dy;
            fn.call(element,event,dx,dy,d,[event,clientX,event.clientY],[original_x,original_y]);
            original_x=0;
            original_y=0;
            original_left=0;
            original_top=0;
         }
      }
   }
}

初始化处理的关键代码:

function init(){
   //地图的初始化省略
   ...
   //zoomin、zoomout后重新同步坐标,并且重绘动画
   dojo.connect(map,'onZoomEnd',function(){
        zoomSVG();
   });
  //鼠标滚动
  SVGEvent.bindEvent("svg","mousewheel",wheel); 
  //鼠标拖动 
  SVGEvent.bindEvent("svg","mouseDrag",drag); //初始化边界坐标
  track.limitXY=[document.body.clientWidth,docment.body.clientHeight];

  //初始化屏幕坐标
  initScreenXY();
  //初始化svg
  initSVG(track);
  //加载轨迹线
  addTrack(track);
}

function initScreenXY(){
  track.x=[];
  track.y=[];
  for(var i=0;i


 
  
 
  
 
  

动画控制的核心代码如下:

function play(){
   if(!processManager.isStart){
      document.getElementById("animateMotion").beginElement();
      processManager.isStart=true;
   }else{
      document.getElementById("svg").unpauseAnimations();
   }
   }
}

function pause(){
   document.getElementById("svg").pauseAnimations();
   processManager.isStart=false;
}

function stop(){
   track.i=0;
   processManager.isStart=false;
   pause();
   clearSVG();
   initScreenXY();
   initSVG(track);
}

function clearSVG(){
   var circle=document.getElementById("circle");
   circle.parentNode.removeChild(circle);
   var motionPath=document.getElementById("motionPath");
   motionPath.parentNode.removeChild(motionPath);
}

zoomin,zoomout,漫游后的处理核心代码如下:

function zoomSVG(){
   document.getElementById("svg").pausseAnimations();
   clearSVG();
   reDrawSVG();
   if(processManager.isStart)
      play();
}

function panSVG(){
   document.getElementById("svg").pausseAnimations();
   clearSVG();
   reDrawSVG();
   if(processManager.isStart)
      play();
}

function reDrawSVG(){
   //初始化剩余路线的坐标信息
   var lon=[];
   var lat=[];
   var x=[];
   var y=[];
   //是否播放到最后一段,最后一段特殊处理
  if(track.i
 
  
 
  
 
  

获得当前点的经纬度,屏幕坐标核心代码如下:

function now(){
   var circle=document.getElementById("circle"); 
   if(circle){
      //当前的屏幕坐标
      var ctm=circle.getCTM();
      var x=circle.getAttribute("cx");
      var y=circle.getAttribute("cy");
      track.nowXY[0]=x*ctm.a+y*ctm.c+ctm.e;
      track.nowXY[1]=x*ctm.b+y*ctm.d+ctm.f;
      //当前的经纬度坐标
      var screenPoint=new esri.geometry.ScreenPoint({
          x:track.nowXY[0],
          y:track.nowXY[1]
      });
      var point=map.toMap(screenPoint);
      track.now[0]=point.x;
      track.now[1]=point.y;
   }
}

实现鼠标点击,滚轮的zoomin,zoomout和鼠标拖动漫游的核心代码如下:

//事件的绑定在init中,这里是绑定的function
function wheel(evt){
   if(evt.deltaY>0){
      zoomIn();
   }
   else{
      zoomOut();
   }
}

function zoomIn(){
   var extent=map.extent;
   map.setExtent(extent.expand(0.5));
}

function zoomOut(){
   var extent=map.extent;
   map.setExtent(extent.expand(2));
}

function drag(event,dx,dy,d,point,originalPoint){
   if(d=="right")
      map.panLeft();
   if(d=="left")
      map.panRight();
   if(d=="up")
      map.panDown();
   if(d=="down")
      map.panUp();
   if(d=="leftup")
      map.panLowerRight();
   if(d=="leftdown")
      map.panUpperRight();
   if(d=="rightup")
      map.panLowerLeft();
   if(d=="rightdown")
      map.panUpperLeft();
}


 
  
 
  
 
  

     

你可能感兴趣的:(arcgis)