(创建页面,内容为“{{未完成}} <html> </html>”) |
无编辑摘要 |
||
| 第1行: | 第1行: | ||
{{Category:公共设施}} | |||
{{未完成}} | {{未完成}} | ||
<html> | <html> | ||
<head> | |||
<style type=""> | |||
canvas{ | |||
width: 100% | |||
} | |||
</style> | |||
<meta charset="utf-8"> | |||
<title>Metro Map!</title> | |||
</head> | |||
<body> | |||
<canvas id="MainMap" width="0" height="0">Oops!</canvas> | |||
<script> | |||
window.dataset = { | |||
"lines": { | |||
"1": { | |||
"color": "#B02E26", | |||
"route": [ | |||
{ "SCZCT": "" }, | |||
{ "CZHCT": "" }, | |||
{ "NNCNL": "" }, | |||
{ "SPAWN": "" }, | |||
{ "MNTDY": "" }, | |||
{ "EYYCT": "" }, | |||
{ "LNYCT": "" } | |||
] | |||
}, | |||
"2": { | |||
"color": "#3C44AA", | |||
"route": [ | |||
{ "WTCCT": "" }, | |||
{ "LNYCT": "" }, | |||
{ "WUMIN": "" }, | |||
{ "XJIAN": "" }, | |||
{ "PGNUN": "" } | |||
] | |||
}, | |||
"5": { | |||
"color": "#8932B8", | |||
"route": [ | |||
{ "SCZCT": "" }, | |||
{ "CZHCT": "" }, | |||
{ "XNMCT": "" }, | |||
{ "MUYLN": "" }, | |||
{ "pos": [-8, 4], "stat": "planned" }, | |||
{ "ACBTF": "" }, | |||
{ "pos": [-12, 2], "stat": "planned" }, | |||
{ "YGHOM": "" }, | |||
{ "pos": [-12, 8], "stat": "planned" }, | |||
{ "pos": [-14, 8], "stat": "planned" }, | |||
{ "SZHCT": "" } | |||
] | |||
}, | |||
"6": { | |||
"color": "#C74EBD", | |||
"route": [ | |||
{ "QIWAN": "" }, | |||
{ "pos": [-6, 12], "stat": "planned" }, | |||
{ "ENSHM": "" }, | |||
{ "CINDA": "" }, | |||
{ "XNMCT": "" }, | |||
{ "pos": [-2, 4], "stat": "planned" }, | |||
{ "GJHOM": "" }, | |||
{ "KEMOW": "" }, | |||
{ "pos": [8, 6], "stat": "planned" }, | |||
{ "KMRPK": "" }, | |||
{ "LINDA": "" }, | |||
{ "XYHOM": "" }, | |||
{ "BREAD": "" }, | |||
{ "ICERF": "" } | |||
] | |||
} | |||
}, | |||
"stations": { | |||
"ACBTF": { | |||
"label": "古战场", | |||
"pos": [-8, 2], | |||
"stat": "planned" | |||
}, | |||
"BREAD": { | |||
"label": "面包", | |||
"pos": [8, -6], | |||
"stat": "planned" | |||
}, | |||
"CINDA": { | |||
"label": "工业区空置域", | |||
"pos": [-6, 6], | |||
"stat": "planned" | |||
}, | |||
"CZHCT": { | |||
"label": "赐召", | |||
"pos": [-2, 2], | |||
"stat": "finished" | |||
}, | |||
"ENSHM": { | |||
"label": "满天星家东", | |||
"pos": [-6, 8], | |||
"stat": "planned" | |||
}, | |||
"EYYCT": { | |||
"label": "漪阳东", | |||
"pos": [0, -4], | |||
"stat": "finished" | |||
}, | |||
"GJHOM": { | |||
"label": "烧仙草家", | |||
"pos": [-2, 6], | |||
"stat": "planned" | |||
}, | |||
"ICERF": { | |||
"label": "冰道", | |||
"pos": [10, -8], | |||
"stat": "planned" | |||
}, | |||
"KEMOW": { | |||
"label": "科魔", | |||
"pos": [4, 6], | |||
"stat": "planned" | |||
}, | |||
"KMRPK": { | |||
"label": "烟草公园", | |||
"pos": [8, 0], | |||
"stat": "finished" | |||
}, | |||
"LINDA": { | |||
"label": "轻工业区", | |||
"pos": [8, -2], | |||
"stat": "planned" | |||
}, | |||
"LNYCT": { | |||
"label": "临漪", | |||
"pos": [0, -6], | |||
"stat": "finished" | |||
}, | |||
"MNTDY": { | |||
"label": "定漪山", | |||
"pos": [0, -2], | |||
"stat": "finished" | |||
}, | |||
"MUYLN": { | |||
"label": "暮阳陵", | |||
"pos": [-6, 4], | |||
"stat": "planned" | |||
}, | |||
"NNCNL": { | |||
"label": "北运河北", | |||
"pos": [0, 2], | |||
"stat": "finished" | |||
}, | |||
"PGNUN": { | |||
"label": "鸽联", | |||
"pos": [2, -10], | |||
"stat": "planned" | |||
}, | |||
"QIWAN": { | |||
"label": "绮湾", | |||
"pos": [-2, 12], | |||
"stat": "planned" | |||
}, | |||
"SCZCT": { | |||
"label": "赐召南", | |||
"pos": [-2, 0], | |||
"stat": "planned" | |||
}, | |||
"SPAWN": { | |||
"label": "主城", | |||
"pos": [0, 0], | |||
"stat": "finished" | |||
}, | |||
"SZHCT": { | |||
"label": "汕州", | |||
"pos": [-14, 10], | |||
"stat": "planned" | |||
}, | |||
"WTCCT": { | |||
"label": "天策西", | |||
"pos": [-2, -6], | |||
"stat": "planned" | |||
}, | |||
"WUMIN": { | |||
"label": "梧鸣", | |||
"pos": [2, -6], | |||
"stat": "planned" | |||
}, | |||
"XJIAN": { | |||
"label": "薪涧", | |||
"pos": [2, -8], | |||
"stat": "planned" | |||
}, | |||
"XNMCT": { | |||
"label": "星眸", | |||
"pos": [-4, 4], | |||
"stat": "finished" | |||
}, | |||
"XYHOM": { | |||
"label": "逍遥家", | |||
"pos": [8, -4], | |||
"stat": "planned" | |||
}, | |||
"YGHOM": { | |||
"label": "叶光", | |||
"pos": [-12, 6], | |||
"stat": "finished" | |||
} | |||
} | |||
} | |||
</script> | |||
<script> | |||
const tilelen = 120 | |||
const BLACK = "#000000" | |||
const LIGHTGRAY = "#AAAAAA" | |||
const WHITE = "#FFFFFF" | |||
function canvPos(x, y) { | |||
x = - Number(minx) + Number(x) + 1 | |||
y = Number(maxy) - Number(y) + 1 | |||
return [Math.round(x * tilelen), Math.round(y * tilelen)] | |||
} | |||
function drawMap(mapData) { | |||
let ctx = this.getContext("2d") | |||
let links = [] | |||
for (let line in mapData.lines) { | |||
let lastpoint = undefined | |||
for (let waypoint in mapData.lines[line].route) { | |||
waypoint = mapData.lines[line].route[waypoint] | |||
if (waypoint.pos == undefined) { | |||
waypoint = mapData.stations[Object.keys(waypoint)[0]] | |||
} | |||
else { | |||
if (waypoint.stat == undefined) { waypoint.stat = "finished" } | |||
} | |||
if (lastpoint != undefined) { | |||
let color = { "finished": mapData.lines[line].color, "planned": LIGHTGRAY } | |||
let stat = "finished" | |||
if (waypoint.stat == "planned" || lastpoint.stat == "planned") stat = "planned" | |||
if (links[[lastpoint.pos, waypoint.pos]] != undefined) { | |||
links[[lastpoint.pos, waypoint.pos]].push([line, color[stat]]) | |||
} | |||
else { | |||
links[[lastpoint.pos, waypoint.pos]] = [[line, color[stat]]] | |||
} | |||
} | |||
lastpoint = waypoint | |||
} | |||
} | |||
// Draw lines | |||
for (let link in links) { | |||
let [x1, y1, x2, y2] = link.split(",") | |||
let linklen = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) | |||
link = links[link] | |||
for (let rail in link) { | |||
let lw = 0.1 | |||
let dl = lw * (rail - (link.length - 1) / 2) * 1.1 | |||
let [dx, dy] = [- (y2 - y1) / linklen * dl, (x2 - x1) / linklen * dl] | |||
let [startx, starty] = canvPos((Number(x1) + Number(dx)), (Number(y1) + Number(dy))) | |||
let [stopx, stopy] = canvPos((Number(x2) + Number(dx)), (Number(y2) + Number(dy))) | |||
ctx.beginPath() | |||
ctx.moveTo(startx, starty) | |||
ctx.lineTo(stopx, stopy) | |||
ctx.lineWidth = lw * tilelen | |||
ctx.lineCap = "square" | |||
ctx.strokeStyle = link[rail][1] | |||
ctx.stroke() | |||
} | |||
} | |||
// Draw stations | |||
for (let station in mapData.stations) { | |||
station = mapData.stations[station] | |||
let stationColor = BLACK | |||
if (station.stat == "planned") stationColor = LIGHTGRAY | |||
let name = station.label | |||
let pos = canvPos(station.pos[0], station.pos[1]) | |||
let [x, y] = pos | |||
ctx.beginPath() | |||
ctx.lineWidth = 1 | |||
ctx.strokeStyle = stationColor | |||
ctx.arc(x, y, 0.225 * tilelen, 0, 2 * Math.PI) | |||
ctx.fillStyle = stationColor | |||
ctx.fill() | |||
ctx.stroke() | |||
ctx.beginPath() | |||
ctx.arc(x, y, 0.15 * tilelen, 0, 2 * Math.PI) | |||
ctx.fillStyle = WHITE | |||
ctx.fill() | |||
ctx.stroke() | |||
ctx.font = Math.round(0.3 * tilelen) + "px Arial" | |||
pos = canvPos(station.pos[0] + 0.2, station.pos[1] + 0.2) | |||
x = pos[0] | |||
y = pos[1] | |||
ctx.fillStyle = stationColor | |||
ctx.fillText(name, x, y) | |||
} | |||
} | |||
let minx = 0, miny = 0, maxx = 0, maxy = 0 | |||
for (let station in dataset.stations) { | |||
station = dataset.stations[station] | |||
let [x, y] = station.pos | |||
if (x > maxx) { maxx = x } | |||
else { if (x < minx) { minx = x } } | |||
if (y > maxy) { maxy = y } | |||
else { if (y < miny) { miny = y } } | |||
} | |||
// [minx, miny, maxx, maxy] = [minx - 1, miny - 1, maxx + 1, maxy + 1] | |||
window.mainMap = document.getElementById("MainMap") | |||
mainMap.setAttribute("width", (maxx - minx + 3) * tilelen) | |||
mainMap.setAttribute("height", (maxy - miny + 2) * tilelen) | |||
mainMap.drawMap = drawMap | |||
mainMap.drawMap(dataset) | |||
</script> | |||
</body> | |||
</html> | </html> | ||