HTML5,不只是看上去很美(第四弹:可交互地铁线路图)

前言

最近特别忙,承蒙大伙关照,3D机房的项目一个接着一个,领了一帮小弟,搞搞传帮带,乌飞兔走,转眼已经菊黄蟹肥……有个小弟很不错,勤奋好学,很快就把API都摸透了,国庆几天自己折腾着做了个HTML5的魔都的地铁线路图,能拖能拽的,还和电子地图做了交互。哥决定把小弟的成果纳入“HTML5,不只是看上去很美”系列,以示鼓励(P.S.
其实还挺有压力的,后浪推前浪,新人赶旧人。我们这些老鸟也得注意,免得让00后给抢了饭碗)

效果图对比

网上的地铁图还是很多的,小弟选了这张比较新的做参考。想当年哥来魔都打拼时,图上可就一红一绿打个叉……暴露年龄的话不多说,看图:

再来看看小弟做的:

我是一眼看不出区别,但这可不是一张效果图,而是一个新手仅用了几天做出来的东西,而且里面许多美化和调整是通过程序自动完成的,这就不容易了。更重要的是,它并不是一张死图,而是纯矢量、可交互、有动态效果、无失真缩放的拓扑图!我们先简单看一下交互效果,后面可以详细说说代码的实现。

文本提示弹弹弹

首先,把鼠标移到站点、路段、图标等位置,都会有文本提示弹出,这个比较基本,百度家的就有,小弟也就放了比较简单的弹出内容。如果加上基本介绍啊、相关提示啊、周边信息啊……要是加上广告,就可以赚钱了……反正什么都可以加嘛,就是一个setToolTip命令而已。

站点图标变变变

当鼠标移到站点上时,站点图标做了放大效果,这个效果很贴心,看了下百度家,用的是发光效果。

实现的方法也很简便,就是在注册站点矢量图形时,加入了动态判断。以下注册普通站点矢量图形的代码:


  1. twaver.Util.registerImage('station',{ 
  2.     w: linkWidth*1.6, 
  3.     h: linkWidth*1.6, 
  4.     v: function (data, view) { 
  5.         var result = []; 
  6.         if(data.getClient('focus')){ 
  7.             result.push({ 
  8.                 shape: 'circle', 
  9.                 r: linkWidth*0.7, 
  10.                 lineColor:  data.getClient('lineColor'), 
  11.                 lineWidth: linkWidth*0.2, 
  12.                 fill: 'white', 
  13.             }); 
  14.             result.push({ 
  15.                 shape: 'circle', 
  16.                 r: linkWidth*0.2, 
  17.                 fill:  data.getClient('lineColor'), 
  18.             }); 
  19.         }else{ 
  20.             result.push({ 
  21.                 shape: 'circle', 
  22.                 r: linkWidth*0.6, 
  23.                 lineColor: data.getClient('lineColor'), 
  24.                 lineWidth: linkWidth*0.2, 
  25.                 fill: 'white', 
  26.             }); 
  27.         } 
  28.         return result; 
  29.     } 
  30. });  

动画效果拽拽拽

从上图还可以看到,在换乘站图标中,除了增加了颜色,还实现了旋转效果。这个就秒杀百度家了。来看代码:


  1. twaver.Util.registerImage('rotateArrow', { 
  2.         w: 124, 
  3.         h: 124, 
  4.         v: [{ 
  5.             shape: 'vector', 
  6.             name: 'doubleArrow', 
  7.             rotate: 360, 
  8.             animate: [{ 
  9.                 attr: 'rotate', 
  10.                 to: 0, 
  11.                 dur: 2000, 
  12.                 reverse: false, 
  13.                 repeat: Number.POSITIVE_INFINITY 
  14.             }] 
  15.         }] 
  16.     });  

当然这对于TWaver来说也很容易,只不过对rotate属性进行了动态改变而已。

另外,在单击和双击站点时,还实现了selected和loading的动画效果,值得点赞!

混合缩放炫炫炫

无失真缩放是矢量图的先天优势,小弟也掌握得炉火纯青,把TWaver的混合缩放模式用到极致,还有缩放比例控制、文字自动隐藏等小功能,方便订制。

代码也不复杂:


  1. network.setZoomManager(new twaver.vector.MixedZoomManager(network)); 
  2. network.setMinZoom(0.2); 
  3. network.setMaxZoom(3); 
  4. network.setZoomVisibilityThresholds({ 
  5. label : 0.6, 
  6. });  

交互功能用起来

小弟很自豪地给我介绍这个功能:图标可以自由拖动,松开后会自动弹回。哥问小弟这有什么用,他一本正经地说:证明图是活的!

好吧你赢了,虽然是个没什么卵用的功能,但闲的蛋疼的时候可以随便玩上几十分钟我也是信的。

连续单击同一站点

连续单击同一站点(注意不是双击),可以将经过此站点的所有线路突出显示出来。小弟说加入这个功能纯粹因为简单易做,我……竟然表示非常理解,谁年轻时没耍过这类轻松又讨好的小招数呢?

双击站点

双击站点,竟然弹出了本站周边的电子地图!知道引入他山之玉,看来小子可教啊。我发现他的定位方法,有的是用经纬度,有的是关键词查询。小弟狡黠地说,开始是人工查每个站点经纬度的,干了一段儿发现太麻烦,后来改路子了。马大大说的,懒人改变世界,我服!

最后来八一八程序设计的思路吧,小弟是棵好苗子,能做出那么像样的程序,必然是深思熟虑过的。不想再听我啰嗦的朋友,也可以直接发邮件给我,tw-service@servasoft.com,来鉴赏下小弟的成果。

数据文件的整理

数据格式,选择了JavaScript原生支持的json文件,直观方便。数据结构,按照站点、线路、杂项三大块来组织,结构清晰,利于遍历、查询等操作。


  1.         "stations":{ 
  2.             "l01s01":{ }, 
  3.             ………… 
  4.         } 
  5.         "lines":{ 
  6.             "l01":{……}, 
  7.             ………… 
  8.         } 
  9.         "sundrys":{ 
  10.             "railwaystationshanghai":{……}, 
  11.             ………… 
  12.         } 
  13.     }  

命名比较规范,通过名字就可以看出基本信息(例如“l01s01”就是1号线第1个站点),甚至直接利用名字就可以进行查询和遍历。


  1. "l01s01":{ 
  2.        "id":"l01s01", 
  3.        "name":"莘庄", 
  4.        "loc":{"x":419,"y":1330}, 
  5.        "label":"bottomright.bottomright", 
  6.    }, 
  7.    …………  

站点路线的创建

首先是读取json文件的数据。


  1. function loadJSON(path,callback){ 
  2.         var xhr = new XMLHttpRequest(); 
  3.         xhr.onreadystatechange = function(){ 
  4.             if (xhr.readyState === 4) { 
  5.                 if (xhr.status === 200) { 
  6.                    dataJson = JSON.parse(xhr.responseText); 
  7.                    callback && callback(); 
  8.                } 
  9.            } 
  10.        }; 
  11.        xhr.open("GET", path, true); 
  12.        xhr.send(); 
  13.     }  

因为读取文件是一个异步的过程,所以要程序的展开都要放在文件读取函数的内部。


  1. function init(){ 
  2.         loadJSON("shanghaiMetro.json", function(){ 
  3.             initNetwork(dataJson); 
  4.             initNode(dataJson); 
  5.         }); 
  6.     }  

只要通过对站点进行一次遍历,车站的建立就完成了。


  1. for(staId in json.stations){ 
  2.         var station = json.stations[staId]; 
  3.         staNode = new twaver.Node({ 
  4.             id: staId, 
  5.             name: station.name, 
  6.             image:'station', 
  7.         }); 
  8.         staNode.s('label.color','rgba(99,99,99,1)'); 
  9.         staNode.s('label.font','12px 微软雅黑'); 
  10.         staNode.s('label.position',station.label); 
  11.         staNode.setClient('location',station.loc); 
  12.         box.add(staNode); 
  13.     }  

再对数据文件中的各条线路下的所有站点进行遍历,在站点间依次创建Link。


  1. for(lineId in json.lines) { 
  2.         …… 
  3.         for(staSn in line.stations) { 
  4.             …… 
  5.             var link = new twaver.Link(linkId,prevSta,staNode); 
  6.             link.s('link.color', line.color); 
  7.             link.s('link.width', linkWidth); 
  8.             link.setToolTip(line.name); 
  9.             box.add(link); 
  10.         } 
  11.     }  

再对label位置进行调整,否则站点名称会显示的很乱。小弟是通过在原始数据中手动加入位置信息来实现的,稍显笨了一点,应该可以通过程序自动判断站点周围空间来进行智能调整。

最后再加入图标,一张原始的地铁图就呈现出来了。

路线拐点的添加

基本的示意功能已经具备了,这里,小弟让我很欣赏的一点是没有就此停止,而是进一步做了调整,使线路只保留了横平竖直和正斜的走向,以达到整齐美观的效果。可能看起来与参考图稍稍有些不同,主要因为各路段基本只添加了一个拐点,这样做既大大简化了程序,又基本保证了图形的美观度。想远一点,做多一点,是块做产品的好料子。

当然为了提高程序的灵活性,应对必须添加两个或以上拐点的情况,也使用了人工拐点的手段。不过这里人工拐点被设成一个隐形的节点,可能利于智能拐点的判断,但也有可能在路线操作时造成混乱。如何处理更好还可以进一步推敲。


  1. var createTurnSta = function(line, staSn){ 
  2.     staTurn = new twaver.Node(staSn); 
  3.     staTurn.setImage(); 
  4.     staTurn.setClient('lineColor',line.color); 
  5.     staTurn.setClient('lines',[line.id]); 
  6.     var loc = line.stations[staSn]; 
  7.     staTurn.setClient('location',loc); 
  8.     box.add(staTurn); 
  9.     return staTurn; 
  10. }  

接点位置的调整

大家可以看到,并不是所有路段都直接连入站点中心,在许多情况下必须要进行偏移。


  1. var createFollowSta = function(json, line, staNode, staId){ 
  2.     staFollow = new twaver.Follower(staId); 
  3.     staFollow.setImage(); 
  4.     staFollow.setClient('lineColor',line.color); 
  5.     staFollow.setClient('lines',[line.id]); 
  6.     staFollow.setHost(staNode); 
  7.     var az = azimuth[staId.substr(6,2)]; 
  8.     var loc0 = json.stations[staId.substr(0,6)].loc; 
  9.     var loc = {x:loc0.x+az.x, y:loc0.y+az.y}; 
  10.     staFollow.setClient('location',loc); 
  11.     box.add(staFollow); 
  12.     return staFollow; 

小弟采取了虚拟节点的办法,就是在站点的旁边,添加一个Follower(但并不显示出来),让并行的不同线路连接到不同的Follower上。通过调整Follower的位置,来实现线路与站点连接点的控制。


  1. var azimuth = { 
  2.     bb: {x: 0, y: linkWidth*zoom/2}, 
  3.     tt: {x: 0, y: -linkWidth*zoom/2}, 
  4.     rr: {x: linkWidth*zoom/2, y: 0}, 
  5.     ll: {x: -linkWidth/2, y: 0}, 
  6.     br: {x: linkWidth*zoom*0.7/2, y: linkWidth*zoom*0.7/2}, 
  7.     bl: {x: -linkWidth*zoom*0.7/2, y: linkWidth*zoom*0.7/2}, 
  8.     tr: {x: linkWidth*zoom*0.7/2, y: -linkWidth*zoom*0.7/2}, 
  9.     tl: {x: -linkWidth*zoom*0.7/2, y: -linkWidth*zoom*0.7/2}, 
  10.     BB: {x: 0, y: linkWidth*zoom}, 
  11.     TT: {x: 0, y: -linkWidth*zoom}, 
  12.     RR: {x: linkWidth*zoom, y: 0}, 
  13.     LL: {x: -linkWidth, y: 0}, 
  14.     BR: {x: linkWidth*zoom*0.7, y: linkWidth*zoom*0.7}, 
  15.     BL: {x: -linkWidth*zoom*0.7, y: linkWidth*zoom*0.7}, 
  16.     TR: {x: linkWidth*zoom*0.7, y: -linkWidth*zoom*0.7}, 
  17.     TL: {x: -linkWidth*zoom*0.7, y: -linkWidth*zoom*0.7} 
  18. };  

介绍到这里就结束了,虽然是个小例子,实在是但美观性和实用性都还过得去,小弟花了心思去做,其实稍加改造就可以做出高铁图、公交图、运行图等应用。设想一下,如果能用在轨道交通列控中心大屏监控里,是多么炫酷。说到这,又想起了前两天云栖大会上刚看到的杭州城市数据大脑,不知何时,哥也能参与一把那样的项目呢?可视化,哥的强项……

作者:MonoLog

来源:51CTO

时间: 2024-12-29 20:02:02

HTML5,不只是看上去很美(第四弹:可交互地铁线路图)的相关文章

看上去很美:国产服务器变革初显锋芒

日前,据媒体报道,国产服务器领军企业--浪潮服务器在2007年上半年取得了重大销售突破,已经连续两个季度相较去年同期保持40%以上的增长率.这是浪潮集团一体化运营整合之后的首份成绩单.由此,国产服务器一场由内而外的主动变革,悄然拉开了序幕-- 看上去很美 服务器市场历来是兵家必争之地. 在90年代,这个领域几乎被国外厂商完全垄断:近几年来,国产服务器.特别是PC服务器经过艰难打拼,终于抢下接近半壁江山:以浪潮和联想为首的中国品牌甚至一度挤入全球服务器市场前十名--可以说,国产服务器已经在激烈的市

投资科技行业:看上去很美 不亏钱很难

科技行业投资:看上去很美 不亏钱很难(腾讯科技配图)腾讯科技讯(童云)北京时间12月29日消息,当惠普在去年8月份同意以1 10亿美元的价格收购英国软件公司Autonomy时,两位知名投资者马上就对这桩大规模并购交易将变现如何做出了完全不同的押注.在过去几年时间里,做空投资者吉姆-查诺斯(Jim Chanos)一直都在对Autonomy举起"红旗",并且从2011年就已经开始做空惠普股票.据一名熟知查诺斯想法的消息人士透露,在他看来,对于惠普这家硅谷科技巨头来说,这项交易不啻于在它的&

月子会所被曝看起来很美:一对一有名无实

月子会所"看起来很美"乱象丛生:无营业执照专业水准低藏安全隐患□记者邹婷玉南宁报道随着经济发展和生活水平的提高,妇女产后"坐月子"越来越受到重视.需求的不断细化使月子会所应运而生.生意火爆,成了"市场新宠",往往需要提前数月预订,有的地方甚至将月子会所看作城市家庭"坐月子"的新标准.然而,<经济参考报>记者近日走访了解到,月子会所这一新兴行业目前处于"灰色地带",无相关营业执照,缺乏监管主体,无

SaaS软件—从“看上去很美”到“用起来很爽”

问题描述 SaaS的风生水起似乎已经有一段时间了,从SAP.微软.Oracle到国内的电信.金蝶.风云网络,越来越多的企业,以"软件+服务"的口号,开始投身于这一新兴领域.但是,SaaS热潮的背后难掩一个令人尴尬的现实,这就是用户的反应与厂商预期之间的反差.仔细分析,产品的集成问题,用户对业务数据信息的安全考量,产品缺乏灵活的自定义功能,已经成为阻碍用户使用SaaS产品的三大"拦路虎".要解决这些问题,使SaaS产品步下神坛,走入"寻常百姓家",

觉得别人的看起来很美的站友

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断淘宝客 站长团购 云主机 技术大厅 每天逛论坛都能看到很多讨论人喜欢讨论那个站那个站更好,有没高手拿下来的帖子,看了以后真的不知道怎么说了 怎么就那么多人喜欢去拿这个站,那个站呢.难道别人的站就是做的有那么好,值得你去把他拿来自己用?真是奇怪的人. 那个站做更好很有用吗?起码对我来说并非是想象中的那么好,我认识的专业人士也有些,很多站,看的时间很好,结果拿下来以后,或者

百度统计 看上去很美!

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断淘宝客 站长团购 云主机 技术大厅 百度也搞网站流量统计服务了,而且也是免费的.在人们心目中,百度是大公司,和51.la.cnzz和51yes比较起来,似乎统计会更精准更可靠,如此说来,广大站长是否要见异思迁,向百度投怀送抱呢?百度的统计首页也用精美的图片明确地标识出百度统计的5大要点(注意,我用的是要点,而非特点,优点):准确.安全.高速.专业.稳定.如此说来,百度统

C2B营销,“大势所趋”还是“看上去很美”?

C2B是电子商务模式的一种,即消费者对企业(Customer to Business).近期,C2B风潮兴起,众多大平台与企业纷纷投入到这个新的战场中,其中天猫的双十一可算是国内C2B比较成功的一场尝试.随着80.90后新生代逐渐成为主流消费群体,这种近乎个性化的定制看起来似乎更能吸引他们的注意力与购买的欲望.但是这种新生的营销模式到底是"大势所趋"还是"看上去很美"? 国外兴起的洋营销适合中国市场么? 最先由美国流行起来的消费者对企业(C2B)模式真的适合在中国的

百度的C2C看起来很美

中介交易 SEO诊断 淘宝客 云主机 技术大厅 近日,百度宣布正式进军电子商务领域,并选取了C2C作为突破口,意欲打造一个中文互联网领域最具规模的网上个人交易平台,这一消息在业界引起了极大波动. 早在2005年眼光锐利的马云,就嗅到了搜索引擎对电子商务巨大的潜在价值:雅虎以搜索起家,虽然其在国外比不上Google,在国内比不上百度,但是从整体意义上来说,雅虎始终排行第二,而05年雅虎中国正是陷入困境的阶段,适时的并购让阿里节省了大量股权,同时对于阿里集团全球化的发展来说,雅虎国际化的优势又要明显

社交化O2O:至少看上去很美

一夜之间,叮咚小区似乎捅破了天,各种流言,从传资金链断裂到承认收缩裁员,那个风光号称拿到1亿美金投资的叮咚,那个北京上海充斥广告的叮咚小区终于栽了第一个大跟头,叮咚小区不会是最后一个在O2O之路上摔跤的人,这次事件仅仅是当前浮躁O2O投资期的一个缩影,也证实了当今O2O快速发展期中的种种问题. O2O,涉及中国13亿人口,3000多县市,最接地气的模式,目前只要是互联网项目,都多少要灌输一些O2O的概念,似乎这样才不落下风,但这次叮咚小区的收缩事件,作为O2O从业者,我们应该从中吸取一些教训.