基於html5繪製上海地鐵圖 - 路況信息展現

前面介紹了上海地鐵圖的繪製,最近有客戶提出了新的需求:雙車道,並顯示路網狀態信息。通過一番研究,在原地鐵圖基礎上作了擴展實現 javascript

Screen Shot 2014-05-13 at 下午12.27.30

交通圖介紹

路況狀態在GIS系統中普遍應用,谷歌地圖,百度地圖都有實時路況的功能,太複雜並不是好事,就像地鐵圖,按真實經緯度呈現反而不夠直觀,交通圖、路網也是如此,去掉無關信息,將有限的數據(路,收費站,路況)展示出來,成爲一種解決方案 html

百度地圖中的路況信息

baidu地圖路況信息 html5

  百度地圖-路況信息

雙車道的繪製

來看具體實現,原來的地鐵圖是一條線表示,改用雙線繪製,可表現來往的方向,canvas並無雙線線形,須要本身實現 java

三種鏈接點類型

雙線的算法相似2d中的stroke算法,stroke拐點有三種方式:尖的、圓角、斜面,考慮到路網拐角不會太尖,因此簡單實現,採用miter方式,沿線各個拐點左右偏移 算法

拐點的三種樣式

繪製雙車道,計算拐點的法線和夾角

function drawDoubleLine(path, points, isDoubleLine, size, lineDirection) {
    var p0, p1;
    Q.forEach(points, function (p) {
        if (!p1) {
            p1 = p;
            return;
        }
        p1._a = Math.atan2(p.y - p1.y, p.x - p1.x);
        if (p0) {
            p1.angle = Math.atan2(Math.sin(p0._a) + Math.sin(p1._a), Math.cos(p0._a) + Math.cos(p1._a));
            p1.angle -= Math.PI / 2;
            var theta = Math.abs(p1._a - p0._a);
            if (theta > Math.PI) {
                theta = 2 * Math.PI - theta;
            }
            p1.inclinedAngle = Math.PI - theta;
        } else {
            p1.angle = p1._a - Math.PI / 2;
        }
        p0 = p1;
        p1 = p;
    });
    p1.angle = Math.atan2(p1.y - p0.y, p1.x - p0.x) - Math.PI / 2;

    if (lineDirection == "left") {
        drawLine(path, points, 0.5, size);
        return;
    }
    if (lineDirection == "right") {
        drawLine(path, points, -0.5, size);
        return;
    }
    if (!isDoubleLine) {
        drawLine(path, points, 0, size);
        return;
    }
    drawLine(path, points, 0.5, size);
    drawLine(path, points, -0.5, size);
}

繪製連線

function drawLine(path, points, yOffset, size, doubleLine) {
    Q.forEach(points, function (p, index) {
        var angle = p.angle;
        var inclinedAngle = p.inclinedAngle;

        var x = p.x, y = p.y;
        var offset = yOffset;
        if (offset) {
            offset *= 2 / 3 * 0.8;
        }
        if (p.yOffset) {
            offset += p.yOffset;
        }
        if (offset) {
            offset *= size;
            if (inclinedAngle) {
                offset /= Math.max(0.2, Math.sin(inclinedAngle / 2));
            }
            var sin = Math.sin(angle);
            var cos = Math.cos(angle);
            x += cos * offset;
            y += sin * offset;
        }
        if (index == 0) {
            path.moveTo(x, y);
        } else {
            path.lineTo(x, y);
        }
    });
}

雙車道呈現效果

雙車道

路況狀態繪製

路況狀態也是呈線條狀,與路網繪製相同,只不過爲單向,仍是上面的繪製函數,參數lineDirection表示車道方向,左側車道偏移50%,右側則偏移-50%,這樣能夠實現兩側不一樣的狀態 json

function drawDoubleLine(path, points, isDoubleLine, size, lineDirection) {
    ...
    if (lineDirection == "left") {
        drawLine(path, points, 0.5, size);
        return;
    }
    if (lineDirection == "right") {
        drawLine(path, points, -0.5, size);
        return;
    }
    ...
}

路況模擬數據

與原來的例子相同,路況信息也能夠經過JSON數據加載,整個爲一個array,集合中每一個元素爲一條路的路況片斷信息,"line"屬性表示所在路線的編號,"fragments"表示路況片斷集合,每一個片斷包含三個屬性,與路線的json表示相同,只不過增長了"direction"屬性,表示片斷的方向 canvas

[{
    "line": "11",
    "fragments": [
        {
            "color": "#FF0000",
            "direction": "right",
            "stations": [230, 231, 232]
        },
        {
            "color": "#FFFF00",
            "direction": "left",
            "stations": [229, 230, 231, 232]
        },
        {
            "color": "#00FF00",
            "direction": "left",
            "stations": [227, 228, 229]
        }
    ]
}]

路況運行效果

上面11號線上的模擬數據,獲得下面的效果路況片斷的繪製 函數

在線演示

在線演示:http://demo.qunee.com/#Shanghai Metro Map 2012 spa

示例下載:路況圖示例.zip code

原文地址:http://blog.qunee.com/?p=4594

相關文章
相關標籤/搜索