不久前看到了QQ地图的测距功能,觉得挺好玩的,就思考模仿一下。本来想通过canvas来画图,可惜对canvas不是很熟悉,就准备用svg了,其实我对svg也不是很熟,纯粹是学习。
代码只是简单的生成图线,没有删除点的功能,也没有拖动路线的功能,demo仅仅是抛砖引玉,大侠就不要拍砖了,我是个菜鸟。
DEMO截图:
素材:
资源:jQuery.js,Raphael.js
思考:
实现测距所需要获取的参数,最基本的两点:
1:比例尺,由于是虚拟的地图,比例尺可以手动设定。
2:路线的长度,可以通过path.getTotalLength()来获取像素长度。
基本知识:
1:svg的路径格式
<path d="M 100 100 L 300 200 L 200 300 z" />
说明:
M 表示移动到当前点 M 100 100 指将当前点移动到坐标(100, 100) 的地方
L 表示绘制直线 "L 300 200" 指从当前位置(100, 100) 绘制直线到 (300, 200) 处
z 表示闭合路径,首尾相连。更多
2:我们使用Raphael这个js操作SVG。其声明path的基本语法,更多
/*String id,divWidth,divHeight*/
var ploy = Raphael('mapPloy', datas.w, datas.h);
var pathslength=ploy.path(options)
获取鼠标发生事件的位置--->添加点--->更新包含svg的DIV的相关属性--->绘图
原理:
代码:
HTML与CSS
<style type="text/css">
#maps{
width:500px;
height:300px;
background:#f9f9f9;
border:1px solid #c6c6c6;
margin:10px auto;
position:relative;
}
div.point{
position:absolute;
width:12px;
height:12px;
background:url(stone.gif) no-repeat;
}
div.svgCotainer{
position:absolute;
}
#mapPloy{
position:absolute;
}
#info{
position:absolute;
top:10px;
right:10px;
width:100px;
height:25px;
background:#ecf6fc;
border:1px solid #8ad0fd;
font-size:14px;
font-family:Arial, Helvetica, sans-serif;
color:#51a961;
text-align:center;
line-height:25px;
}
</style>
<div id="maps">
<div id="info">
</div>
</div>
1首先写个获取数组中最大值,最小值的方法,主要是为了获取所有点Top与Left的最大值与最小值
//return array's max
Array.prototype.max = function(){
return Math.max.apply({}, this);
}
//return array's min
Array.prototype.min = function(){
return Math.min.apply({}, this);
}
var options={
cssClickClass:'point',//点击时生成点的类
svgCtnCls:'svgContainer',//svg容器的类
wapper:'#maps',//地图容器
scale:'1'//比例尺
};
var Ploy={
getData:function(){
var arrayTop=[];
var arrayLeft=[];
var el=$('div.'+options.cssClickClass);
$.each(el,function(i,n){
var pointTop=$(n).position().top;
var pointLeft=$(n).position().left;
arrayTop.push(pointTop);
arrayLeft.push(pointLeft);
});
var minTop=arrayTop.min();
var maxTop=arrayTop.max();
var minLeft=arrayLeft.min();
var maxLeft=arrayLeft.max();
var svgWidth=maxLeft-minLeft+el.width();
var svgHeight=maxTop-minTop+el.height();
return {
w:svgWidth,
h:svgHeight,
minTop:minTop,
minLeft:minLeft,
elWidth:el.width(),
elHeight:el.height()
}
},
makeSvgContainer:function(){
var s=this;
var datas=s.getData();
var div=$('#mapPloy').is('div');
if(!div){
var svgContainer=$('<div/>')
.attr('id','mapPloy')
.addClass(options.svgCtnCls)
.css({
width:datas.w,
height:datas.h,
top:datas.minTop+datas.elHeight/2,
left:datas.minLeft+datas.elWidth/2
}).prependTo($(options.wapper));
}else{
$('#mapPloy').css({
width:datas.w,
height:datas.h,
top:datas.minTop+datas.elHeight/2,
left:datas.minLeft+datas.elWidth/2
})
}
},
//添加点在地图区域中
addPoint:function(top,left){
var wapper=$(options.wapper);
var t=wapper.offset().top;
var l=wapper.offset().left;
var pt=top-t;
var pl=left-l;
var point=$('<div/>').addClass(options.cssClickClass)
.css({
top:pt,
left:pl,
poisiton:'absolute'
})
.appendTo(wapper);
},
makePoly:function(el,o){
var s=this;
s.addPoint(o.top,o.left);
s.makeSvgContainer();
//清空svg,重新画图
$(el).find('div.'+options.svgCtnCls).empty();
//遍历已经有的点,做出路线
var points=$('div.'+options.cssClickClass);
var datas=s.getData();
//生成路径
var path=""
$.each(points,function(i,n){
if(i==0){
path+="M";
}else{
path+="L";
}
var leftInSvg=$(n).position().left-datas.minLeft;
var TopInSvg=$(n).position().top-datas.minTop;
path += leftInSvg;
path += ",";
path += TopInSvg;
path += " ";
});
var ploy = Raphael('mapPloy', datas.w, datas.h);
var pathslength=ploy.path(path).attr({
stroke:'#1791fc',
'stroke-width':3,
opacity:.7,
fill:"none"});
//计算距离
return pathslength.getTotalLength()*options.scale;
}
}
$(document).ready(function(){
$('#maps').click(function(e){
var left=e.pageX;
var top=e.pageY;
var o={
left:left,
top:top
}
var lengths=Ploy.makePoly('#maps',o);
lengths=(Math.round(lengths*100))/100;
$('#info').html(lengths+'Km');
})
});