A municipal project uses a subway map to display the Shanghai subway station and related information flows. It is a little slow to use the HTML5 technology and find an HTML5 graphic component-Qunee for HTML5, after a simple study, we can effectively solve such needs and make a beautiful presentation. The following uses the Shanghai 2012 Metro map as an example. The effect is as follows:
Example
First, you need to solve the data problem. You can obtain it from Wikipedia or the Shanghai Metro official website. However, you do not have to manually record the site location to achieve good display results, you also need to set the ideal position of the text label. Sometimes, to avoid text overlay, you need to set the rotation angle ...... In short, the problem is artificial. Think of a solution to solve the data problem. In addition, the powerful display effect of the Qunee graphic component is used to create an interactive online subway map.
Data format
Data in JSON format can be divided into three types: Text tags, sites, and subway lines.
The overall structure is as follows:
{"labels" : [ ... ],"stations" : [ ... ],"lines" : [ ... ]}
Text tag data
Contains coordinates and text information. If the text needs to be rotated, the "rotate" attribute is added. The following is the "xinzhuang" text tag information.
{"Text": "xinzhuang", "x": 883.591, "y": 1625.695}
Text and node rotation effect
Site Data
Contains coordinates, rotation angles, and numbers. The following is the information of the "xinzhuang" station.
{"id" : 5,"x" : 869.8513512641732,"y" : 1597.6559686949402,"rotate" : 0.7853981633974483}
Subway Line Data
Contains the name, color, and the site ID
{"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]}
In special cases, for example, if two subway lines share one line, the two lines will overlap. To avoid this situation, you can also specify the horizontal offset of the site, such as the following data in line 1 above.
{"id": 21, "yOffset": 0.5}
Because there are many lines shared by Shanghai Metro Line 3 and line 4, this processing is more obvious.
Line 3 data
{"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]}
Effect of Metro connection
Create an element
Data needs to be converted to a qunee primitive object. Three types of functions must be created for each of the three types.
Create text tag
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;}
Create site
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;}
Create subway lines
CreateLine (...) The function is used to create a subway line. It uses the node type Elements and sets the node subject as the path. The function updateLine (...) Used to automatically generate a line path from the site information
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); } })}
Interactive Processing
Added interactive processing, listened to site drag events, and kept the subway route unchanged
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]); } } });});
Online example
Http://demo.qunee.com/#Shanghai Metro Map 2012