(终于弄得差不多了)
无编辑摘要
第2行: 第2行:
{{未完成}}
{{未完成}}
<html>
<html>
<head>
  <style type="">
    canvas{
            width: 100%
        }
    </style>
  <meta charset="utf-8">
  <title>Metro Map!</title>
</head>
<body>
<body>
  <canvas id="MainMap" width="0" height="0">Oops!</canvas>
    <div id="MainMap"></div>
  <script>
    <script>
    window.dataset = {
        window.dataset = {
             "lines": {
             "lines": {
                 "1": {
                 "1": {
第122行: 第111行:
                         { "ENSHM": "" },
                         { "ENSHM": "" },
                         { "WNSHM": "" },
                         { "WNSHM": "" },
                         { "pos": [-11.75, 8], "stat": "planned" },
                         { "pos": [-12, 8], "stat": "planned" },
                         { "YGHOM": "" }
                         { "YGHOM": "" }
                     ]
                     ]
第310行: 第299行:
             }
             }
         }
         }
  </script>
    </script>
  <script>
    <script>
    const tilelen = 120
         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 * tilelen), Math.round(y * tilelen)]
             return [Math.round(x), Math.round(y)]
         }
         }


         function drawMap(mapData) {
         function drawMap(mapData, lineGet) {
             let ctx = this.getContext("2d")
             // 处理只显示单条的情况
            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
 
             /* 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)
                 link = links[link]
                 linkInfo = links[link]
                 for (let rail in link) {
                 for (let rail in linkInfo) {
                    let lw = 0.1
                     let dl = (rail - (linkInfo.length - 1) / 2) * 0.25
                     let dl = lw * (rail - (link.length - 1) / 2) * 1.1
                     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] = canvPos((Number(x1) + Number(dx)), (Number(y1) + Number(dy)))
                     let [startx, starty] = [
                     let [stopx, stopy] = canvPos((Number(x2) + Number(dx)), (Number(y2) + Number(dy)))
                            50 + (Number(x1) / size * 50) + "%",
                     ctx.beginPath()
                            50 - (Number(y1) / size * 50) + "%"
                     ctx.moveTo(startx, starty)
                        ]
                     ctx.lineTo(stopx, stopy)
                     let [stopx, stopy] = [
                     ctx.lineWidth = lw * tilelen
                            50 + (Number(x2) / size * 50) + "%",
                     ctx.lineCap = "square"
                            50 - (Number(y2) / size * 50) + "%"
                     ctx.strokeStyle = link[rail][1]
                        ]
                     ctx.stroke()
 
                    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)
                    }
                 }
                 }
             }
             }
             // Draw stations
            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 pos = canvPos(station.pos[0], station.pos[1])
                 let [x, y] = station.pos
                 let [x, y] = pos
 
                ctx.beginPath()
                 // <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
                 ctx.lineWidth = 1
                 const point = document.createElementNS('http://www.w3.org/2000/svg','circle')
                 ctx.strokeStyle = stationColor
                 point.dataset.raw = station.pos
                ctx.arc(x, y, 0.225 * tilelen, 0, 2 * Math.PI)
                 point.setAttribute("cx", 50 + (Number(x) / size * 50) + "%")
                 ctx.fillStyle = stationColor
                 point.setAttribute("cy", 50 - (Number(y) / size * 50) + "%")
                ctx.fill()
                 point.style.transition = "r .3s, stroke-width .3s"
                 ctx.stroke()
                 point.style.r = "0.5rem"
                ctx.beginPath()
                 point.style.fill = WHITE
                ctx.arc(x, y, 0.15 * tilelen, 0, 2 * Math.PI)
                 point.style.stroke = stationColor
                 ctx.fillStyle = WHITE
                 point.style.strokeWidth = "0.2rem"
                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
                point.onmouseover = function()  { onPointOver(point)    }
                point.onmouseleave = function() { onPointLeace(point)  }


        for (let station in dataset.stations) {
                // <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


            station = dataset.stations[station]
                if(gSite.children.length == 0) {
            let [x, y] = station.pos
                    gSite.append(point)
            if (x > maxx) { maxx = x }
                    gSite.append(text)
            else { if (x < minx) { minx = x } }
                } else {
             if (y > maxy) { maxy = y }
                    gSite.insertBefore(point, gSite.firstChild)
             else { if (y < miny) { miny = y } }
                    gSite.insertBefore(text, gSite.firstChild)
                }
             }
             this.append(gSite)
         }
         }


         // [minx, miny, maxx, maxy] = [minx - 1, miny - 1, maxx + 1, maxy + 1]
         // 整图大小
        let minx = 0, miny = 0, maxx = 0, maxy = 0, size = 0, adx = 0, ady = 0, view = 900


         window.mainMap = document.getElementById("MainMap")
         // 初始化
         mainMap.setAttribute("width", (maxx - minx + 3) * tilelen)
        const div = document.getElementById("MainMap")                // SVG 框架
         mainMap.setAttribute("height", (maxy - miny + 2) * tilelen)
        // 生成 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)
  </script>
 
        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>

2022年6月22日 (三) 08:26的版本

Icon-warn.png
内容未完成
本页面内容处于未完成状态。