(终于弄得差不多了) |
Stapx Steve(讨论 | 贡献) 无编辑摘要 |
||
| 第2行: | 第2行: | ||
{{未完成}} | {{未完成}} | ||
<html> | <html> | ||
<body> | <body> | ||
<div id="MainMap"></div> | |||
<script> | |||
window.dataset = { | |||
"lines": { | "lines": { | ||
"1": { | "1": { | ||
| 第122行: | 第111行: | ||
{ "ENSHM": "" }, | { "ENSHM": "" }, | ||
{ "WNSHM": "" }, | { "WNSHM": "" }, | ||
{ "pos": [- | { "pos": [-12, 8], "stat": "planned" }, | ||
{ "YGHOM": "" } | { "YGHOM": "" } | ||
] | ] | ||
| 第310行: | 第299行: | ||
} | } | ||
} | } | ||
</script> | |||
<script> | |||
const BLACK = "#000000" | const BLACK = "#000000" | ||
const LIGHTGRAY = "#AAAAAA" | const LIGHTGRAY = "#AAAAAA" | ||
| 第320行: | 第308行: | ||
x = - Number(minx) + Number(x) + 1 | x = - Number(minx) + Number(x) + 1 | ||
y = Number(maxy) - Number(y) + 1 | y = Number(maxy) - Number(y) + 1 | ||
return [Math.round(x | return [Math.round(x), Math.round(y)] | ||
} | } | ||
function drawMap(mapData) { | function drawMap(mapData, lineGet) { | ||
let | // 处理只显示单条的情况 | ||
if(lineGet != undefined && mapData["lines"][lineGet] != undefined) { | |||
// 处理线路列表 | |||
const lineShow = mapData["lines"][lineGet] | |||
mapData["lines"] = {} | |||
mapData["lines"][lineGet] = lineShow | |||
// 处理站点列表(删除不需要的站点) | |||
for (let station in mapData.stations) { | |||
let get = false | |||
for(let site in mapData["lines"][lineGet]["route"]) { | |||
if(Object.keys(mapData["lines"][lineGet]["route"][site]) == station) { | |||
get = true | |||
break | |||
} | |||
} | |||
if(!get) { | |||
delete mapData.stations[station] | |||
} | |||
} | |||
} | |||
// 计算全图大小 | |||
for (let station in mapData.stations) { | |||
station = mapData.stations[station] | |||
let [x, y] = station.pos | |||
maxx = Math.max(maxx, x) | |||
maxy = Math.max(maxy, y) | |||
minx = Math.min(minx, x) | |||
miny = Math.min(miny, y) | |||
} | |||
size = Math.max(Math.abs(maxx) + Math.abs(minx), Math.abs(maxy) + Math.abs(miny)) * 0.55 | |||
// 计算中心偏移 | |||
adx = (minx + maxx) / 2 | |||
ady = (miny + maxy) / 2 | |||
// 开始显示 | |||
let links = [] | let links = [] | ||
for (let line in mapData.lines) { | for (let line in mapData.lines) { | ||
| 第354行: | 第375行: | ||
} | } | ||
} | } | ||
/ | |||
/* Draw lines */ | |||
// 构建线条图层 | |||
const gLine = document.createElementNS('http://www.w3.org/2000/svg','g') | |||
gLine.id = "LineList" | |||
gLine.style.transform = "translateX(" + adx / size * 50 + "%)" | |||
gLine.style.transform = "translateY(" + ady / size * 50 + "%)" | |||
for (let link in links) { | for (let link in links) { | ||
let [x1, y1, x2, y2] = link.split(",") | let [x1, y1, x2, y2] = link.split(",") | ||
let linklen = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) | let linklen = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) | ||
linkInfo = links[link] | |||
for (let rail in | for (let rail in linkInfo) { | ||
let dl = (rail - (linkInfo.length - 1) / 2) * 0.25 | |||
let dl = | |||
let [dx, dy] = [- (y2 - y1) / linklen * dl, (x2 - x1) / linklen * dl] | let [dx, dy] = [- (y2 - y1) / linklen * dl, (x2 - x1) / linklen * dl] | ||
let [startx, starty] = | let [startx, starty] = [ | ||
let [stopx, stopy] = | 50 + (Number(x1) / size * 50) + "%", | ||
50 - (Number(y1) / size * 50) + "%" | |||
] | |||
let [stopx, stopy] = [ | |||
50 + (Number(x2) / size * 50) + "%", | |||
50 - (Number(y2) / size * 50) + "%" | |||
] | |||
const line = document.createElementNS('http://www.w3.org/2000/svg','line') | |||
line.dataset.raw = link | |||
line.dataset.name = linkInfo[rail][0] | |||
line.setAttribute("x1", startx) | |||
line.setAttribute("y1", starty) | |||
line.setAttribute("x2", stopx) | |||
line.setAttribute("y2", stopy) | |||
line.style.strokeWidth = "0.25rem" | |||
line.style.strokeLinecap = "round" | |||
line.style.stroke = linkInfo[rail][1] | |||
line.style.transition = "stroke-width .3s" | |||
// 偏移 | |||
let move = "" | |||
if(dx > 0) { | |||
move += "translateX(0.15rem) " | |||
} else if(dx < 0) { | |||
move += "translateX(-0.15rem) " | |||
} | |||
if(dy > 0) { | |||
move += "translateY(0.15rem) " | |||
} else if(dy < 0) { | |||
move += "translateY(-0.15rem) " | |||
} | |||
line.style.transform = move | |||
// 鼠标事件 | |||
line.onmouseover = function() { onLineHover(line) } | |||
line.onmouseleave = function() { onLineLeave(line) } | |||
if(gLine.children.length == 0) { | |||
gLine.append(line) | |||
} else { | |||
gLine.insertBefore(line, gLine.firstChild) | |||
} | |||
} | } | ||
} | } | ||
/ | this.append(gLine) | ||
/* Draw stations */ | |||
// 构建站点图层 | |||
const gSite = document.createElementNS('http://www.w3.org/2000/svg','g') | |||
gSite.style.transform = "translateX(" + adx / size * 50 + "%)" | |||
gSite.style.transform = "translateY(" + ady / size * 50 + "%)" | |||
for (let station in mapData.stations) { | for (let station in mapData.stations) { | ||
station = mapData.stations[station] | station = mapData.stations[station] | ||
| 第380行: | 第447行: | ||
if (station.stat == "planned") stationColor = LIGHTGRAY | if (station.stat == "planned") stationColor = LIGHTGRAY | ||
let name = station.label | let name = station.label | ||
let [x, y] = station.pos | |||
let [x, y] = pos | |||
// <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/> | |||
const point = document.createElementNS('http://www.w3.org/2000/svg','circle') | |||
point.dataset.raw = station.pos | |||
point.setAttribute("cx", 50 + (Number(x) / size * 50) + "%") | |||
point.setAttribute("cy", 50 - (Number(y) / size * 50) + "%") | |||
point.style.transition = "r .3s, stroke-width .3s" | |||
point.style.r = "0.5rem" | |||
point.style.fill = WHITE | |||
point.style.stroke = stationColor | |||
point.style.strokeWidth = "0.2rem" | |||
point.onmouseover = function() { onPointOver(point) } | |||
point.onmouseleave = function() { onPointLeace(point) } | |||
// <text x="0" y="15" fill="red">I love SVG</text> | |||
const text = document.createElementNS('http://www.w3.org/2000/svg','text') | |||
text.setAttribute("x", 50 + (Number(x) / size * 50) + "%") | |||
text.setAttribute("y", 50 - (Number(y) / size * 50) + "%") | |||
text.style.transform = "translateX(0.7rem) translateY(-0.7rem)" | |||
text.style.fontSize = "0.6rem" | |||
text.style.fill = BLACK | |||
text.innerHTML = name | |||
if(gSite.children.length == 0) { | |||
gSite.append(point) | |||
gSite.append(text) | |||
} else { | |||
gSite.insertBefore(point, gSite.firstChild) | |||
gSite.insertBefore(text, gSite.firstChild) | |||
} | |||
} | |||
this.append(gSite) | |||
} | } | ||
// | // 整图大小 | ||
let minx = 0, miny = 0, maxx = 0, maxy = 0, size = 0, adx = 0, ady = 0, view = 900 | |||
// 初始化 | |||
mainMap.setAttribute(" | const div = document.getElementById("MainMap") // SVG 框架 | ||
mainMap.setAttribute(" | // 生成 SVG | ||
// <svg width="100vh" height="100%" view-box="0 0 2048 2048"> | |||
window.mainMap = document.createElementNS('http://www.w3.org/2000/svg','svg') | |||
mainMap.setAttribute('version','1.1') | |||
mainMap.setAttribute("viewBox", "0 0 " + view + " " + view) | |||
mainMap.setAttribute("preserveAspectRatio", "xMidYMid meet") | |||
mainMap.style.width = '100vh' | |||
mainMap.style.height = '100%' | |||
mainMap.drawMap = drawMap | mainMap.drawMap = drawMap | ||
mainMap.drawMap(dataset) | mainMap.drawMap(dataset) | ||
div.append(mainMap) | |||
</script> | |||
<script> | |||
// 线段悬停事件 | |||
function onLineHover(sender) { | |||
// 线名 | |||
const name = sender.dataset.name | |||
// 寻找所有线段 | |||
const list = document.getElementById("LineList").children | |||
for(let i=0; i<=list.length; i++) { | |||
if(list[i] != undefined && list[i].dataset.name == name) { | |||
list[i].style.strokeWidth = "0.4rem" | |||
} | |||
} | |||
} | |||
function onLineLeave(sender) { | |||
// 线名 | |||
const name = sender.dataset.name | |||
// 寻找所有线段 | |||
const list = document.getElementById("LineList").children | |||
for(let i=0; i<=list.length; i++) { | |||
if(list[i] != undefined && list[i].dataset.name == name) { | |||
list[i].style.strokeWidth = "0.25rem" | |||
} | |||
} | |||
} | |||
// 站点悬停事件 | |||
function onPointOver(sender) { | |||
sender.style.r = "1px" | |||
sender.style.strokeWidth = "1rem" | |||
} | |||
function onPointLeace(sender) { | |||
sender.style.r = "0.5rem" | |||
sender.style.strokeWidth = "0.2rem" | |||
} | |||
</script> | |||
</body> | </body> | ||
</html> | </html> | ||