前言最近很忙,感谢大家的关心,3D机房的项目一个接一个,带领了一批小弟们教教他们,五飞兔没了,一转眼就胖了。。。有个小弟人很好,勤奋好学,很快就把API搞出来了。国庆这几天,做了一张魔都的HTML5地铁地图,可拖拽,与电子地图互动。兄弟决定把弟弟的成果写在《HTML5,不只是长得漂亮》系列里,以示鼓励(P.S.其实压力挺大的,新人赶老,我们老手也要注意一下,免得让2000年以后,我的工作被抢了)比起网上的地铁图,效果图还是很多的。我选择了这个比较新的作为参考。想当年弟弟来上海打拼的时候,照片上有红叉和绿叉。。。暴露年龄不多说,看图:来看看弟弟是干什么的did:一眼看不出区别,但是很神奇它不是效果图,而是一个新手短短几天做出来的东西,里面的很多美化和调整都是通过程序自动完成的,这并不容易。更重要的是,它不是一张死图,而是一张纯矢量、交互式、动态效果、无缩放的拓扑图!先简单看一下交互效果,后面再详细说代码的实现。文字提示BouncingBouncing首先,将鼠标移动到站点、路段、图标等处,会弹出文字提示。这个比较基础,百度就有。小弟也放了一个比较简单的弹窗内容。加基本介绍,相关提示,周边信息……加广告,就可以赚钱……反正加什么都可以,就是一个setToolTip命令。站点图标正在更改。当鼠标移动到站点时,站点图标被放大,这个效果很贴心。看完百度首页,用的是发光效果。实现方法也很简单,就是在注册站点矢量图的时候加上动态判断。常用站点注册矢量图的代码如下:twaver.Util.registerImage('station',{w:linkWidth*1.6,h:linkWidth*1.6,v:function(data,view){varresult=[];if(data.getClient('focus')){result.push({shape:'circle',r:linkWidth*0.7,lineColor:data.getClient('lineColor'),lineWidth:linkWidth*0.2,fill:'white',});result.push({shape:'circle',r:linkWidth*0.2,fill:data.getClient('lineColor'),});}else{result.push({shape:'circle',r:linkWidth*0.6,lineColor:data.getClient('lineColor'),lineWidth:linkWidth*0.2,fill:'white',});}returnresult;}});从上图可以看到动画效果,改变了站内图标,除了添加颜色,还实现了旋转效果。秒杀百度。看代码:twaver.Util.registerImage('rotateArrow',{w:124,h:124,v:[{shape:'vector',name:'doubleArrow',rotate:360,animate:[{属性:'旋转',至:0,持续时间:2000,反向:假,重复:Number.POSITIVE_INFINITY}]}]});当然这对于TWaver来说也很容易,只不过rotate属性是动态变化的。另外,在点击和双击站点时,还实现了选中和加载的动画效果,值得点赞!混合缩放,炫目无失真缩放是矢量图的先天优势,小弟也掌握得很好,将TWaver的混合缩放模式用到了极致,还有缩放比例控制等小功能和自动文本隐藏,方便定制。代码并不复杂:network.setZoomManager(newtwaver.vector.MixedZoomManager(network));network.setMinZoom(0.2);network.setMaxZoom(3);network.setZoomVisibilityThresholds({label:0.6,});使用交互功能自豪地向我介绍这个功能:图标可以自由拖动,松开时会自动弹回。哥哥问弟弟这有什么用,弟弟一本正经地说:证明这幅画是活的!好吧,你赢了,虽然是个没用的功能,但是有空的时候可以玩个几十分钟。我也相信。的。连续点击同一个站点连续点击同一个站点(不是双击)将突出显示所有经过该站点的线路。小哥说加这个功能纯粹是因为简单好做。我……其实很能表达我的理解。这种轻松又讨人喜欢的招数,谁小时候没有用过呢?双击站点,双击站点,弹出站点周边电子地图!知道他山玉的介绍,看来这小子还能教书。我发现他的定位方式有的是用经纬度,有的是用关键词查询。小弟狡黠地说,一开始每个站点的经纬度都是人工查的,但是过了一段时间觉得太麻烦了,后来换了个方式。马达说的,懒人改变世界,我深信!最后说一下818编程的思路。弟弟是个好苗子。能做出这么像样的节目,一定是经过深思熟虑的。不想听我啰嗦的朋友也可以直接给我发邮件,tw-service@servasoft.com,欣赏小弟的成就。数据文件的数据格式整理,选择JavaScript原生支持的json文件,直观方便。数据结构按照站点、线路、杂项三大块组织。结构清晰,便于遍历、查询等操作。{"stations":{"l01s01":{},...}"lines":{"l01":{...},...}"sundrys":{"railwaystationshanghai":{...},…………}}命名比较规范,通过名字可以看出基本信息(比如“l01s01”是1号线首站),甚至可以直接使用查询遍历名字。"l01s01":{"id":"l01s01","name":"新庄","loc":{"x":419,"y":1330},"label":"bottomright.bottomright",},…………站点路由的创建首先是读取json文件的数据。functionloadJSON(path,callback){varxhr=newXMLHttpRequest();xhr.onreadystatechange=function(){if(xhr.readyState===4){if(xhr.status===200){dataJson=JSON.parse(xhr.responseText);callback&&callback();}}};xhr.open("GET",path,true);xhr.send();}因为读取文件是一个异步过程,所以程序的扩展必须放在里面的文件读取功能。functioninit(){loadJSON("shanghaiMetro.json",function(){initNetwork(dataJson);initNode(dataJson);});}只要遍历一次站点,就完成了站点的建立。for(staIdinjson.stations){varstation=json.stations[staId];staNode=newtwaver.Node({id:staId,name:station.name,image:'station',});staNode.s('label.color','rgba(99,99,99,1)');staNode.s('label.font','12px微软雅黑');staNode.s('label.position',station.label);staNode.setClient('location',station.loc);box.add(staNode);}然后遍历数据文件中每一行下的所有站,依次创建站与站之间的Links。for(lineIdinjson.lines){...for(staSninline.stations){...varlink=newtwaver.Link(linkId,prevSta,staNode);link.s('link.color',line.color);链接。s('link.width',linkWidth);link.setToolTip(line.name);box.add(link);}}调整标签的位置,否则站点名称会显示的很乱。小哥是通过在原始数据上手动添加位置信息来实现的,有点傻,应该可以通过程序自动判断场地周围的空间来进行智能调整。最后加上图标,就呈现出一张原汁原味的地铁图。添加路线拐点的基本指示功能已经可用。在这里,我真正欣赏的是,它并没有止步于此,而是做了进一步的调整,让路线只保留了水平、垂直和正斜方向,做到了整洁和美观。影响。可能和参考图看起来略有不同,主要是每个路段只加了一个拐点,这样不仅大大简化了程序,也基本保证了图形的美观性。想的远,做的多,是做产品的好材料。当然,为了提高程序的灵活性,应对必须加入两个或多个拐点的情况,也会采用人工拐点。但这里将人工拐点设置为不可见的节点,可能有利于智能拐点的判断,但也可能造成路线运行时的混乱。如何更好地处理它可以进一步推敲。varcreateTurnSta=function(line,staSn){staTurn=newtwaver.Node(staSn);staTurn.setImage();staTurn.setClient('lineColor',line.color);staTurn.setClient('lines',[line.id]);varloc=line.stations[staSn];staTurn.setClient('location',loc);box.add(staTurn);returnstaTurn;}可以看到并不是所有的路段都直接连接到车站中心,在许多情况必须抵消。varcreateFollowSta=function(json,line,staNode,staId){staFollow=newtwaver.Follower(staId);staFollow.setImage();staFollow.setClient('lineColor',line.color);staFollow.setClient('lines',[line.id]);staFollow.setHost(staNode);varaz=azimuth[staId.substr(6,2)];varloc0=json.stations[staId.substr(0,6)].loc;varloc={x:loc0.x+az.x,y:loc0.y+az.y};staFollow.setClient('location',loc);box.add(staFollow);returnstaFollow;}小弟采用了虚拟节点的方式,即在站点旁边,添加一个Follower(但不显示),这样平行的不同线路可以连接到不同的Followers。通过调整Follower的位置,实现对线站连接点的控制。varazimuth={bb:{x:0,y:linkWidth*zoom/2},tt:{x:0,y:-linkWidth*zoom/2},rr:{x:linkWidth*zoom/2,y:0},ll:{x:-linkWidth/2,y:0},br:{x:linkWidth*zoom*0.7/2,y:linkWidth*zoom*0.7/2},bl:{x:-linkWidth*zoom*0.7/2,y:linkWidth*zoom*0.7/2},tr:{x:linkWidth*zoom*0.7/2,y:-linkWidth*zoom*0.7/2},tl:{x:-linkWidth*zoom*0.7/2,y:-linkWidth*zoom*0.7/2},BB:{x:0,y:linkWidth*zoom},TT:{x:0,y:-linkWidth*zoom},RR:{x:linkWidth*zoom,y:0},LL:{x:-linkWidth,y:0},BR:{x:linkWidth*zoom*0.7,y:linkWidth*zoom*0.7},BL:{x:-linkWidth*zoom*0.7,y:linkWidth*zoom*0.7},TR:{x:linkWidth*zoom*0.7,y:-linkWidth*zoom*0.7},TL:{x:-linkWidth*zoom*0.7,y:-链接宽度*缩放*0.7}};介绍到此结束。虽然是个小例子,但美观和实用性都还不错。弟弟花了很多时间来做。其实稍加修改就可以做出一张高铁图。公交地图、运营地图等应用。想象一下,如果能用在轨道交通列控中心的大屏监控上,该有多酷啊。说到这里,我想起了前两天刚在云栖大会上看到的杭州城市数据大脑。不知道什么时候,我也可以参与这样的项目?可视化,我的实力……最后,想看程序,或者想玩《地铁陀螺欢乐》的朋友可以给我留言,发邮件:tw-service@servasoft.com。
