svg.js 7.93 KB
var gb_real_gps_svg = (function () {
    var _lineCode;
    var _upDown;
    var wrap = '#real_gps_data_page';

    //显示站点svg
    var showSvg = function (lineCode, upDown, cb) {
        _lineCode = lineCode;
        _upDown = upDown;

        if (!_lineCode)
            return;
        $.get('/geo_data/stations/' + _lineCode, function (rs) {
            drawSvgCharts(rs.stations[_upDown]);
            $('.svg_charts', wrap).perfectScrollbar({suppressScrollX: true});
            cb && cb(rs);
        });
    };

    var drawSvgCharts = function (data) {
        var len = data.length;
        var h = len * 65;

        var yScale = d3.scale.linear().range([30, h - 30]).domain([0, len - 1]);
        var cx = 105;
        var cy = function (d, i) {
            return yScale(i);
        };
        var tText = function (d, i) {
            return d.name.replace('(', '(').replace(')', ')');
        };

        var line = d3.svg.line().x(cx).y(yScale);

        $(wrap + ' .svg_charts svg').empty();
        var svg = d3.select(wrap + ' .svg_charts svg').style('height', h);
        //add item g
        var items = svg.selectAll('g.item').data(data)
            .enter().append('g').classed({
                'item': true
            });

        //text
        items.append('text').classed({'station_text': true})
            .text(tText)
            .attr('x', cx)
            .attr('y', cy);

        //path
        items.append('path').classed({'station_link': true})
            .attr('d', function (d, i) {
                return i < len - 1 ? line([i, i + 1]) : '';
            });

        //circle
        items.append('circle').classed({'station_circle': true})
            .attr('cx', cx)
            .attr('cy', cy)
            .attr('data-id', function (d) {
                return d.stationCode + "_" + d.upDown;
            });

        //circle num
        items.append('text').classed({'circle_no': true})
            .attr('x', function (d, i) {
                return i >= 9 ? cx - 4.7 : cx - 1;
            })
            .attr('y', cy)
            .text(function (d, i) {
                return i + 1;
            });

        svg.append('g').classed({
            'gps-wrap': true
        });
    }

    //退出
    exitCallbackFun = function () {
        clearTimeout(timer);
        _lineCode = null;
    };

    var delay = 1000 * 5;
    var timer;
    var start_gps = function () {
        if (!_lineCode) {
            alert('无法获取线路编码');
            return;
        }

        if (timer)
            clearTimeout(timer);

        (function () {
            var f = arguments.callee;
            refresh(function () {
                timer = setTimeout(f, delay);
            });
        })();
    };

    var refresh = function (cb) {
        $.ajax({
            url: '/gps/findByLineAndUpDown',
            data: {lineCode: _lineCode, upDown: _upDown, t: Math.random()},
            dataType: 'json',
            success: function (rs) {
                renderGps(rs);
                cb();
            },
            error: function (xr, t) {
                gb_utils.showNotification('连接服务器失败', '刷新GPS失败,稍后重试', 'danger');
                cb();
            }
        });
    };

    var renderGps = function (rs) {
        var arr = rs.list;
        //排序
        arr.sort(function (a, b) {
            if (a.inOut == 2)
                return -1;
            if (b.inOut == 2)
                return 1;
            return a.stationNo - b.stationNo;
        });

        //时间处理
        for (var i = 0, len = arr.length; i < len; i++) {
            arr[i].secStr = seconds2Str(arr[i].seconds);
            arr[i].secStr2 = seconds2Str(arr[i].seconds2);
            arr[i].zdsj = seconds2Str(rs.forecast[arr[i].deviceId]);
            arr[i].timeStr = moment(arr[i].timestamp).format('YYYY-MM-DD HH:mm.ss');
        }

        //渲染svg
        draw_gps(arr);

        //渲染表格
        if ($('.data_list', wrap).is(":visible")) {
            var htmlStr = template('real_gps_table_list-temp', rs);
            $('.data_list table tbody', wrap).html(htmlStr);
            $('.data_list', wrap).perfectScrollbar({suppressScrollX: true});
        }

        //渲染地图
        if ($('.map_wrap', wrap).is(":visible")) {
            gb_real_gps_map.renderGps(arr);
        }
    };

    /**
     * 画gps
     * @param arr
     */
    var line_gps_index = {};
    var groupByStationAndUpdown = function (data) {
        var rs = {},
            key;
        $.each(data, function () {
            key = this['stationCode'] + '_' + this['upDown'];
            if (!rs[key])
                rs[key] = [];

            rs[key].push(this);
        });

        return rs;
    };
    var gps_index_mapp = function (data) {
        var rs = {};
        var dataGroupStop = groupByStationAndUpdown(data);
        for (var stopNo in dataGroupStop) {
            rs[stopNo] = {};
            $.each(dataGroupStop[stopNo], function (i, gps) {
                rs[stopNo][gps.deviceId] = i;
            });
        }
        return rs;
    };

    var gps_key = function (d) {
        return d.deviceId;
    };

    var tx_id = function (d) {
        return 'tx_' + d.deviceId;
    };
    var g_text = function (d) {
        return !d.nbbm ? 'null' : d.nbbm.replace('-', '');
    };

    function draw_gps(data) {
        line_gps_index = gps_index_mapp(data);

        var svg = d3.select(wrap + ' .svg_charts svg');
        var gps_cont = svg.select('.gps-wrap');
        //rect
        var rects = gps_cont.selectAll('rect').data(data, gps_key);
        rects.enter().append('rect').attr('_id', function (d) {
            return 'rct_' + d.deviceId;
        });
        rects.exit().remove();

        gps_update_point(rects, svg);

        //text
        var ts = gps_cont.selectAll('text').data(data, gps_key);
        ts.enter().append('text')
            .attr('_id', tx_id);
        ts.exit().remove();
        ts.text(g_text)
        gps_update_point(ts, svg);
    }

    var get_circle = function (dataId, svg) {
        try {
            var circle = $('.station_circle[data-id=' + dataId + ']', svg[0]);
            if (circle.length == 0)
                circle = null;
        } catch (e) {
            console.log('get_circle error! station_circle data-id:' + dataId);
            return null;
        }
        return circle;
    };

    var gx = function (gps, svg, wrapId) {
        var circle = get_circle(gps.stationCode + '_' + gps.upDown, svg);
        if (!circle) return -300;

        var x = circle.attr('cx') - 80;
        return x;
    };

    var gy = function (gps, svg) {
        var circle = get_circle(gps.stationCode + '_' + gps.upDown, svg);
        if (!circle) return -300;

        var cy = parseInt(circle.attr('cy')),
            index = line_gps_index[gps.stationCode + '_' + gps.upDown][gps.deviceId];

        if (index >= 3)
            return -100;
        return cy + (index * 19);
    };

    function gps_update_point(e, svg) {
        var x;

        e.attr('x', function (d) {
            x = gx(d, svg);
            if (x == -100)
                $(this).css('transition-duration', 0).hide();
            else
                $(this).show();//找不到停靠点,直接隐藏
            return x;
        })
            .attr('y', function (d) {
                return gy(d, svg);
            })
            .attr('updown', function (d) {
                return d.upDown;
            });
    }

    function seconds2Str(seconds) {
        if(!seconds)
            return null;
        var minutes = parseInt(seconds / 60)
            , s = seconds % 60;
        return minutes + '分' + s + "秒";
    }

    return {
        showSvg: showSvg,
        start_gps: start_gps
    }
})();