摘要:哥決定把小弟的成果納入,不只是看上去很美系列,以示鼓勵其實還挺有壓力的,后浪推前浪,新人趕舊人。連續(xù)單擊同一站點連續(xù)單擊同一站點注意不是雙擊,可以將經(jīng)過此站點的所有線路突出顯示出來。
前言
最近特別忙,承蒙大伙關(guān)照,3D機房的項目一個接著一個,領(lǐng)了一幫小弟,搞搞傳幫帶,烏飛兔走,轉(zhuǎn)眼已經(jīng)菊黃蟹肥……有個小弟很不錯,勤奮好學(xué),很快就把API都摸透了,國慶幾天自己折騰著做了個HTML5的魔都的地鐵線路圖,能拖能拽的,還和電子地圖做了交互。哥決定把小弟的成果納入“HTML5,不只是看上去很美”系列,以示鼓勵(P.S. 其實還挺有壓力的,后浪推前浪,新人趕舊人。我們這些老鳥也得注意,免得讓00后給搶了飯碗)
效果圖對比網(wǎng)上的地鐵圖還是很多的,小弟選了這張比較新的做參考。想當(dāng)年哥來魔都打拼時,圖上可就一紅一綠打個叉……暴露年齡的話不多說,看圖:
再來看看小弟做的:
我是一眼看不出區(qū)別,但這可不是一張效果圖,而是一個新手僅用了幾天做出來的東西,而且里面許多美化和調(diào)整是通過程序自動完成的,這就不容易了。更重要的是,它并不是一張死圖,而是純矢量、可交互、有動態(tài)效果、無失真縮放的拓?fù)鋱D!我們先簡單看一下交互效果,后面可以詳細(xì)說說代碼的實現(xiàn)。
文本提示彈彈彈首先,把鼠標(biāo)移到站點、路段、圖標(biāo)等位置,都會有文本提示彈出,這個比較基本,百度家的就有,小弟也就放了比較簡單的彈出內(nèi)容。如果加上基本介紹啊、相關(guān)提示啊、周邊信息啊……要是加上廣告,就可以賺錢了……反正什么都可以加嘛,就是一個setToolTip命令而已。
站點圖標(biāo)變變變當(dāng)鼠標(biāo)移到站點上時,站點圖標(biāo)做了放大效果,這個效果很貼心,看了下百度家,用的是發(fā)光效果。
實現(xiàn)的方法也很簡便,就是在注冊站點矢量圖形時,加入了動態(tài)判斷。以下注冊普通站點矢量圖形的代碼:
twaver.Util.registerImage("station",{ w: linkWidth*1.6, h: linkWidth*1.6, v: function (data, view) { var result = []; 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", }); } return result; } });動畫效果拽拽拽
從上圖還可以看到,在換乘站圖標(biāo)中,除了增加了顏色,還實現(xiàn)了旋轉(zhuǎn)效果。這個就秒殺百度家了。
來看代碼:
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. });
當(dāng)然這對于TWaver來說也很容易,只不過對rotate屬性進(jìn)行了動態(tài)改變而已。
另外,在單擊和雙擊站點時,還實現(xiàn)了selected和loading的動畫效果,值得點贊!
無失真縮放是矢量圖的先天優(yōu)勢,小弟也掌握得爐火純青,把TWaver的混合縮放模式用到極致,還有縮放比例控制、文字自動隱藏等小功能,方便訂制。
代碼也不復(fù)雜:
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. });交互功能用起來
小弟很自豪地給我介紹這個功能:圖標(biāo)可以自由拖動,松開后會自動彈回。哥問小弟這有什么用,他一本正經(jīng)地說:證明圖是活的!
好吧你贏了,雖然是個沒什么卵用的功能,但閑的蛋疼的時候可以隨便玩上幾十分鐘我也是信的。
連續(xù)單擊同一站點連續(xù)單擊同一站點(注意不是雙擊),可以將經(jīng)過此站點的所有線路突出顯示出來。小弟說加入這個功能純粹因為簡單易做,我……竟然表示非常理解,誰年輕時沒耍過這類輕松又討好的小招數(shù)呢?
雙擊站點雙擊站點,竟然彈出了本站周邊的電子地圖!知道引入他山之玉,看來小子可教啊。我發(fā)現(xiàn)他的定位方法,有的是用經(jīng)緯度,有的是關(guān)鍵詞查詢。小弟狡黠地說,開始是人工查每個站點經(jīng)緯度的,干了一段兒發(fā)現(xiàn)太麻煩,后來改路子了。馬大大說的,懶人改變世界,我服!
最后來八一八程序設(shè)計的思路吧,小弟是棵好苗子,能做出那么像樣的程序,必然是深思熟慮過的。不想再聽我啰嗦的朋友,也可以直接發(fā)郵件給我,tw-service@servasoft.com,來鑒賞下小弟的成果。
數(shù)據(jù)文件的整理數(shù)據(jù)格式,選擇了JavaScript原生支持的json文件,直觀方便。
數(shù)據(jù)結(jié)構(gòu),按照站點、線路、雜項三大塊來組織,結(jié)構(gòu)清晰,利于遍歷、查詢等操作。
1. { 2. "stations":{ 3. "l01s01":{ }, 4. ………… 5. } 6. "lines":{ 7. "l01":{……}, 8. ………… 9. } 10. "sundrys":{ 11. "railwaystationshanghai":{……}, 12. ………… 13. } 14. }
命名比較規(guī)范,通過名字就可以看出基本信息(例如“l(fā)01s01”就是1號線第1個站點),甚至直接利用名字就可以進(jìn)行查詢和遍歷。
1. "l01s01":{ 2. "id":"l01s01", 3. "name":"莘莊", 4. "loc":{"x":419,"y":1330}, 5. "label":"bottomright.bottomright", 6. }, 7. …………站點路線的創(chuàng)建
首先是讀取json文件的數(shù)據(jù)。
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. }
因為讀取文件是一個異步的過程,所以要程序的展開都要放在文件讀取函數(shù)的內(nèi)部。
1. function init(){ 2. loadJSON("shanghaiMetro.json", function(){ 3. initNetwork(dataJson); 4. initNode(dataJson); 5. }); 6. }
只要通過對站點進(jìn)行一次遍歷,車站的建立就完成了。
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. }
再對數(shù)據(jù)文件中的各條線路下的所有站點進(jìn)行遍歷,在站點間依次創(chuàng)建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位置進(jìn)行調(diào)整,否則站點名稱會顯示的很亂。小弟是通過在原始數(shù)據(jù)中手動加入位置信息來實現(xiàn)的,稍顯笨了一點,應(yīng)該可以通過程序自動判斷站點周圍空間來進(jìn)行智能調(diào)整。
最后再加入圖標(biāo),一張原始的地鐵圖就呈現(xiàn)出來了。
路線拐點的添加基本的示意功能已經(jīng)具備了,這里,小弟讓我很欣賞的一點是沒有就此停止,而是進(jìn)一步做了調(diào)整,使線路只保留了橫平豎直和正斜的走向,以達(dá)到整齊美觀的效果。可能看起來與參考圖稍稍有些不同,主要因為各路段基本只添加了一個拐點,這樣做既大大簡化了程序,又基本保證了圖形的美觀度。想遠(yuǎn)一點,做多一點,是塊做產(chǎn)品的好料子。
當(dāng)然為了提高程序的靈活性,應(yīng)對必須添加兩個或以上拐點的情況,也使用了人工拐點的手段。不過這里人工拐點被設(shè)成一個隱形的節(jié)點,可能利于智能拐點的判斷,但也有可能在路線操作時造成混亂。如何處理更好還可以進(jìn)一步推敲。
var createTurnSta = function(line, staSn){ staTurn = new twaver.Node(staSn); staTurn.setImage(); staTurn.setClient("lineColor",line.color); staTurn.setClient("lines",[line.id]); var loc = line.stations[staSn]; staTurn.setClient("location",loc); box.add(staTurn); return staTurn; }接點位置的調(diào)整
大家可以看到,并不是所有路段都直接連入站點中心,在許多情況下必須要進(jìn)行偏移。
var createFollowSta = function(json, line, staNode, staId){ staFollow = new twaver.Follower(staId); staFollow.setImage(); staFollow.setClient("lineColor",line.color); staFollow.setClient("lines",[line.id]); staFollow.setHost(staNode); var az = azimuth[staId.substr(6,2)]; var loc0 = json.stations[staId.substr(0,6)].loc; var loc = {x:loc0.x+az.x, y:loc0.y+az.y}; staFollow.setClient("location",loc); box.add(staFollow); return staFollow; }
小弟采取了虛擬節(jié)點的辦法,就是在站點的旁邊,添加一個Follower(但并不顯示出來),讓并行的不同線路連接到不同的Follower上。通過調(diào)整Follower的位置,來實現(xiàn)線路與站點連接點的控制。
var azimuth = { 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: -linkWidth*zoom*0.7} };
介紹到這里就結(jié)束了,雖然是個小例子,實在是但美觀性和實用性都還過得去,小弟花了心思去做,其實稍加改造就可以做出高鐵圖、公交圖、運行圖等應(yīng)用。設(shè)想一下,如果能用在軌道交通列控中心大屏監(jiān)控里,是多么炫酷。說到這,又想起了前兩天云棲大會上剛看到的杭州城市數(shù)據(jù)大腦,不知何時,哥也能參與一把那樣的項目呢?可視化,哥的強項……
最后,想要看程序,或者想玩“地鐵拖拖樂”的各位,都可以給我留言和發(fā)郵件:tw-service@servasoft.com。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92359.html
摘要:兩個月前是的,兩個月過去了,歲月如梭,哥幫小弟做的魔都地鐵拖拖樂打了下廣告,沒想到一炮而紅,好評如潮。下面進(jìn)入正題一些基本功能這里不再贅述,大家可以查看上一篇有關(guān)魔都地鐵圖的文章。一旦地鐵發(fā)生故障,會導(dǎo)致大量乘客滯留。 兩個月前(是的,兩個月過去了,歲月如梭),哥幫小弟做的HTML5魔都地鐵拖拖樂打了下廣告,沒想到一炮而紅,好評如潮。現(xiàn)在的年輕人,還是很上進(jìn)的,一被表揚,動力無窮。年...
摘要:在文末,我會附上一個可加載的模型方便學(xué)習(xí)中文藝術(shù)字渲染用原生可以很容易地繪制文字,但是原生提供的文字效果美化功能十分有限。 showImg(https://segmentfault.com/img/bVWYnb?w=900&h=385); WebGL 可以說是 HTML5 技術(shù)生態(tài)鏈中最為令人振奮的標(biāo)準(zhǔn)之一,它把 Web 帶入了 3D 的時代。 初識 WebGL 先通過幾個使用 Web...
閱讀 1040·2019-08-30 12:57
閱讀 2114·2019-08-30 11:11
閱讀 2177·2019-08-29 15:20
閱讀 1870·2019-08-29 14:12
閱讀 3274·2019-08-28 17:51
閱讀 2378·2019-08-26 13:23
閱讀 787·2019-08-26 10:34
閱讀 3844·2019-08-23 12:37