某市政项目要用到地铁图,展示上海地铁站点以及相关信息流,尝试使用HTML5技术来实现,自己折腾有点慢,找到一个HTML5的图形组件-Qunee for HTML5,简单学习一下,就可以很好的解决这类需求,做出优美的展现,下面以上海2012地铁图为例,效果如下:
示例讲解
首先需要解决数据问题,可以从维基百科或者上海地铁官网中获取,不过也免不了人工,要达到良好的显示效果,需要不只要记录站点的位置,还需要设置文本标签的理想位置,有时为了避免文字叠加,需要设置旋转角度……总之事在人为,想想办法,最终解决了数据问题,再加上Qunee图形组件的强大展示效果,做出来可以交互的在线地铁图
数据格式
采用JSON格式数据,分三种类型:文本标签、站点、地铁线
总的结构如下:
- {
- "labels" : [ ... ],
- "stations" : [ ... ],
- "lines" : [ ... ]
- }
文本标签数据
包含坐标和文字信息,如果文字需要旋转,则会增加”rotate”属性,下面是“莘庄”文本标签信息
- {
- "text" : "莘庄",
- "x" : 883.591,
- "y" : 1625.695
- }
文字与节点旋转效果
站点数据
包含坐标、旋转角度以及编号信息,下面是“莘庄”站的信息
- {
- "id" : 5,
- "x" : 869.8513512641732,
- "y" : 1597.6559686949402,
- "rotate" : 0.7853981633974483
- }
地铁线数据
包含名称,颜色,以及经过的站点编号
- {
- "name" : "1",
- "color" : "#e52035",
- "stations" : [64, 70, 67, 71, 72, 65, 69, 73, 66, 68, 63, 62, 22, 61, 60, {"id": 21, "yOffset": 0.5}, 59, {"id": 18, "yOffset": -0.5}, 17, 58, 14, 7, 57, 6,
- 56, 44, 47, 5]
- }
对于特殊情况,比如两条地铁线共用一条线路的情况,会出现两条线重合,为了避免这种情况,还可以指定站点横向偏移量,比如上面一号线中的如下数据
- {"id": 21, "yOffset": 0.5}
因为上海地铁三号线与四号线共用线路较多,所以这种处理更加明显
三号线数据
- {
- "name" : "3",
- "color" : "#f9d300",
- "stations" : [6, 95, 96, 97, {"id":12,"yOffset":0.5}, {"id":11,"yOffset":0.5}, {"id":8,"yOffset":0.5}, {"id":9,"yOffset":0.5},
- {"id":10,"yOffset":0.5}, {"id":25,"yOffset":0.5}, {"id":26,"yOffset":0.5}, {"id":238,"yOffset":0.5}, {"id":22,"yOffset":-0.5}, {"id":27,"yOffset":-0.5},
- 98, 99, 100, 101, 104, 105, 107, 108, 109, 106, 110, 111]
- }
地铁共线效果
创建图元
数据需要转换成qunee图元对象,三种类型分别对应三个创建函数
创建文本标签
- function createText(name, x, y, rotate){
- var text = graph.createNode(name, x, y);
- if(rotate){
- text.rotate = rotate;
- }
- text.zIndex = 20;
- text.image = null;
- text.setStyle(Q.Styles.BACKGROUND_COLOR, Q.toColor(0x88FFFFFF));
- text.setStyle(Q.Styles.LABEL_ANCHOR_POSITION, Q.Position.LEFT_BOTTOM);
- text.setStyle(Q.Styles.LABEL_POSITION, Q.Position.CENTER_MIDDLE);
- text.setStyle(Q.Styles.LABEL_PADDING, PADDING);
- return text;
- }
创建站点
- function createStation(station){
- var node = graph.createNode(null/**station.name*/, station.x, station.y);
- node.stationId = station.id;
- node.setStyle(Q.Styles.LABEL_FONT_SIZE, 10);
- node.setStyle(Q.Styles.LABEL_ANCHOR_POSITION, Q.Position.CENTER_MIDDLE);
- node.setStyle(Q.Styles.LABEL_POSITION, Q.Position.CENTER_MIDDLE);
- node.zIndex = 10;
- if(station.rotate){
- node.image = roundRect;
- node.rotate = station.rotate;
- }else{
- node.image = circle;
- }
- node.setStyle(Q.Styles.SHAPE_FILL_COLOR, "#FFF");
- node.setStyle(Q.Styles.SHAPE_STROKE_STYLE, "#000");
- return node;
- }
创建地铁线
createLine(…)函数用于创建地铁线,使用了节点类型图元,并设置节点主体为路径,函数updateLine(…)用于从站点信息自动生成线路路径
- function createLine(line){
- var stations = line.stations;
-
- var node = graph.createNode(line.name);
- node.stations = stations;
- node.movable = false;
- node.setStyle(Q.Styles.LABEL_FONT_SIZE, 50);
- node.setStyle(Q.Styles.LABEL_COLOR, line.color);
- node.setStyle(Q.Styles.LABEL_ANCHOR_POSITION, Q.Position.LEFT_BOTTOM);
- node.setStyle(Q.Styles.LABEL_POSITION, Q.Position.LEFT_TOP);
- node.setStyle(Q.Styles.LAYOUT_BY_PATH, true);
- node.anchorPosition = null;
- node.setStyle(Q.Styles.SHAPE_STROKE, size);
- node.setStyle(Q.Styles.SHAPE_STROKE_STYLE, line.color);
-
- updateLine(node, true);
- return node;
- }
- function updateLine(line, addListener){
- var path = new Q.Path();
- line.image = path;
-
- var stations = line.stations;
- var first = true;
- Q.forEach(stations, function(s){
- var station = getStation(s.id || s);
- if(!station){
- return;
- }
- if(addListener){
- addLocationChangeListener(station.stationId, line);
- }
- var location = station.location;
- var x = location.x, y = location.y;
- if(s.yOffset){
- var offset = s.yOffset * size;
- var rotate = station.rotate || 0;
- var sin = Math.sin(rotate);
- var cos = Math.cos(rotate);
- x += cos * offset;
- y += sin * offset;
- }
- if(first){
- first = false;
- path.moveTo(x, y);
- }else{
- path.lineTo(x, y);
- }
- })
- }
交互处理
增加交互处理,监听站点拖动事件,保持地铁路线跟随站点位置变化
- graph.interactionDispatcher.addListener(function(evt){
- if(evt.kind != Q.InteractionEvent.ELEMENT_MOVING){
- return;
- }
- var datas = evt.datas;
-
- Q.forEach(datas, function(data){
- if(!data.stationId){
- return;
- }
- var listeners = stationLocationChangeListeners[data.stationId];
- if(listeners){
- for(var l in listeners){
- updateLine(listeners[l]);
- }
- }
- });
- });
在线示例
来源:http://blog.chinaunix.net/uid-29563534-id-4171575.html

本文解釋瞭如何使用< audio>元素,包括用於格式選擇的最佳實踐(MP3,OGG Vorbis),文件優化和JavaScript控件用於播放。 它強調使用多個音頻f

本文解釋瞭如何創建和驗證HTML5表格。 它詳細介紹了>元素,輸入類型(文本,電子郵件,編號等)和屬性(必需,模式,最小,最大)。 HTML5的優勢比舊方法形成

本文討論了使用HTML5頁面可見性API來檢測頁面可見性,提高用戶體驗並優化資源使用情況。關鍵方麵包括暫停媒體,減少CPU負載以及基於可見性變化管理分析。

本文討論了使用視口元標記來控制移動設備上的頁面縮放,重點是寬度和初始尺度之類的設置,以獲得最佳響應和性能。

本文討論了使用GeOlocation API管理用戶位置隱私和權限,並強調要求權限,確保數據安全性並遵守隱私法律的最佳實踐。

本文使用JavaScript詳細介紹了創建Interactive HTML5遊戲。 它涵蓋了遊戲設計,HTML結構,CSS樣式,JavaScript邏輯(包括事件處理和動畫)以及音頻集成。 必需的JavaScript庫(Phaser,Pi

本文介紹瞭如何使用HTML5拖放API來創建交互式用戶界面,詳細介紹了使元素可拖動的步驟,處理關鍵事件並通過自定義反饋來增強用戶體驗。它還討論了一個常見的陷阱

本文解釋了HTML5 Websockets API,用於實時雙向客戶服務器通信。 它詳細詳細介紹了客戶端(JavaScript)和服務器端(Python/Flask)的實現,以應對可伸縮性,狀態管理,一個挑戰


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SublimeText3漢化版
中文版,非常好用

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SublimeText3 Linux新版
SublimeText3 Linux最新版

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。