想起来自己也是学习地理信息系统专业的学生,于是想着还是要做点和地理信息系统有关系的事情才对.
于是想用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();
}
好了,到这里,三个功能就都实现了(漫游,滚轮缩放,拖框放大)。地图操作的基本功能有了。以后还准备做一点打点,加入地理信息的功能。等做好了再弄上来。