svg+JS 實現 的一個小GIS


想起來自己也是學習地理信息系統專業的學生,於是想着還是要做點和地理信息系統有關系的事情才對.

於是想用svg來實現一個小的地理信息系統.

想來應該是很酷的東西~

老師給我介紹了了一個叫做Raphael的開源庫.利用這個可以做出很多svg的漂亮效果,並且添加事件也會很容易。(謝!)

Raphael的網址是:http://raphaeljs.com

大家可以看一下,上面有很多的例子.並且文檔也很詳細.

有一個中文的在線文檔,地址是http://julying.com/lab/raphael-js/docs/

好了。下面來說如何實現:

首先.一個GIS系統,需要地理底圖,這里因為找不到合適的矢量圖,我從網上找了一個柵格圖,然后用inkscape簡單的矢量化了一下.將就用吧~

 

好了咱們給它命名為mapHB.svg。

然后我們要把這個圖導入成為底圖:

(ps:因為最近使用的是thinkphp的框架做東西,所以這里也是使用的thinkphp框架來做的~)

在php這邊,我們要把svg的信息讀出:

1      $fileName="./Public/Svg/mapHB.svg";
2         $content=file_get_contents($fileName);
3         //讀出svg文件內容4         //替換掉svg文本中的換行。避免SVGimport出錯。
5          $content=preg_replace( "([\r\n])","", $content);
6          $this->assign("content",$content);

讀出后assign在content上。然后在模板這邊畫上,首先,我們要引入一些庫。

1 <script type="text/javascript" src="__PUBLIC__/Js/raphael.2.1.0.min.js"></script><!--Raphael-->
2 <script type="text/javascript" src="__PUBLIC__/Js/raphael-svg-import.js"></script><!--svg導入-->
3 
4 <script type="text/javascript" src="__PUBLIC__/Js/jquery.js"></script>
5 <script type="text/javascript" src="__PUBLIC__/Js/jquery.mousewheel.min.js"></script><!--這個是滾輪事件的jquery庫-->

第一個是raphael的庫,第二個是svg導入的庫。最后一個是鼠標滾輪事件的庫。

好,現在要導入svg圖:

var box=document.getElementById('paper');
//這里是滾輪事件。這里paper是一個全局變量
//paper的_viewBox屬性原本是沒有的,但是在設置setViewBox后就有了。所以要先對paper使用setViewBox
//當然縮放過程必須按照比例來。
                $('#paper').mousewheel(function(event, delta, deltaX, deltaY) {
                    if(delta>0){
                        var sX=paper._viewBox[0];
                        var sY=paper._viewBox[1];
                        var sW=paper._viewBox[2];
                        var sH=paper._viewBox[3];
                        var bili=sH/sW;
                        var H=70*bili;
                        if(sW-70>0&&sH-H>0){
                            paper.setViewBox(sX+35,sY+H/2,sW-70,sH-H);
                        }
                    }else{
                        var sX=paper._viewBox[0];
                        var sY=paper._viewBox[1];
                        var sW=paper._viewBox[2];
                        var sH=paper._viewBox[3];
                        var bili=sH/sW;
                        var H=70*bili;
                        paper.setViewBox(sX-35,sY-H/2,sW+70,sH+H);
                    }            
                });      
//這里是設置畫布的大小  需要調整一下。
                paper = Raphael("paper",box.clientWidth-20,window.innerHeight-45);
                
//這里就是導入svg圖像。
                var newSet = paper.importSVG('{$content}');

導入成功后,我們要給地圖做拖動事件,也就是gis里的漫游,基本思想是:因為在原有的導入的svg上拖動的話,由於填充問題,有的地方不能響應raphael的drag事件,所以我們可以新建一個極大的rect,來覆蓋整個地圖,以及周圍區域。並用透明色填充。這樣可以看見底圖,並且可以響應拖動。

 

當然我們要做3個功能,漫游,拖框放大,滾輪縮放。區分這三個功能的方法,我是用的鼠標樣式,首先點擊功能按鈕,改變鼠標樣式,然后在和地圖交互的過程中,判斷鼠標的樣式,就可以知道是什么功能。

改變樣式的實現如下:

         $('#move').click(function(){
                document.getElementById('paper').style.cursor="move";
                }).mouseover(function(){
                    $('#move').animate({
                        width:30
                    });
                }).mouseout(function(){
                    $('#move').animate({
                        width:24
                    });
                });
                $('#zoomAll').click(function(){
                    paper.setViewBox(0,0,box.clientWidth,box.clientHeight,true);
                }).mouseover(function(){
                    $('#zoomAll').animate({
                        width:30
                    });
                }).mouseout(function(){
                    $('#zoomAll').animate({
                        width:24
                    });
                });
                $('#zoom').click(function(){
                    document.getElementById('paper').style.cursor="nw-resize";
                }).mouseover(function(){
                    $('#zoom').animate({
                        width:30
                    });
                }).mouseout(function(){
                    $('#zoom').animate({
                        width:24
                    });
                });

然后,我們就可以根據樣式來做各種功能了。

我們先來看看drag事件的用法:

Element.drag(onmove, onstart, onend, [mcontext], [scontext], [econtext])

前3個函數是必須的,一個是在鼠標拖動過程中的事件,一個是開始拖動的事件,一個是結束拖動的事件。

onmove有5個參數(dx,dy,x,y,event);

分別是x移動距離,y移動距離,鼠標位置x,y。

onstart有3個參數(x,y,event);

就是鼠標的x,y

onend只有一個(event)

首先是move(漫游):

直接在onmove事件添加這個function就可以實現:

if(action=="move"){
   x0=paper._viewBox[0]-dx/30;
   y0=paper._viewBox[1]-dy/30;
   W=paper._viewBox[2];
   H=paper._viewBox[3];
   paper.setViewBox(x0,y0,W,H,true);
}

然后是拖框放大:

基本思想是,拖框,畫出一個矩形,然后根據矩形的寬度來按照比例調整viewBox大小,這樣就可以實現縮放。

首先開始拖動的時候,記錄下來開始拖動的點。但是要把鼠標的clientx,y轉換成畫布的位置坐標:

              if(action=="nw-resize"){
                        //獲取畫布上的坐標
                        var box=document.getElementById('paper');
                        
                        var scrollX;
                        var scrollY;
                        if(window.scrollX||window.scrollY){
                            scrollX=window.scrollX;
                            scrollY=window.scrollY;
                        }else{
                            scrollX=document.documentElement.scrollLeft;
                            scrollY=document.documentElement.scrollTop;
                        }
                        var bx=$('#paper').offset().left-scrollX;
                        var by=$('#paper').offset().top-scrollY;
                        //var bx=0;
                        //var by=0;
                        var zoombiliW=originalScaleW/paper._viewBox[2];
                        var zoombiliH=originalScaleH/paper._viewBox[3].toFixed(0);
                        var mx=((event.clientX-bx)/zoombiliW+paper._viewBox[0]);
                        var my=((event.clientY-by)/zoombiliH+paper._viewBox[1]);
                        DstartX=mx;
                        DstartY=my;
                      }

然后在onmove中就要畫rect了:

            if(action=="nw-resize"){
                        var zoombiliW=originalScaleW/paper._viewBox[2];
                        var zoombiliH=originalScaleH/paper._viewBox[3].toFixed(0);
              //存在area的話先remove,這樣才能有拖框的效果
                        if(area){
                            area.remove();
                            area=paper.rect(DstartX,DstartY,dx/zoombiliW,dy/zoombiliH);
                        }
                        else{
                            area=paper.rect(DstartX,DstartY,dx/zoombiliW,dy/zoombiliH);
                        }
                        
                    }

最后在onend里,就要根據rect來放大了:

            if(action=="nw-resize"){
                        
                        var x=area.attrs.x;
                        var y=area.attrs.y;
                        var width=area.attrs.width;
                        var sW=paper._viewBox[2];
                        var sH=paper._viewBox[3];
                        var bili=sH/sW;
                        var height=width*bili;
                        paper.setViewBox(x,y,width,height);
              //最后還是把框remove掉咯。
                        area.remove();
                        
                    }

好了,到這里,三個功能就都實現了(漫游,滾輪縮放,拖框放大)。地圖操作的基本功能有了。以后還准備做一點打點,加入地理信息的功能。等做好了再弄上來。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM