(jQuery,SVG)使用jQuery和svg仿QQ地图测距功能(抛砖引玉)
不久前看到了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'); }) });