问题是这样的。公司是social game游戏公司,在各个大型SNS平台都有自己的游戏(多个)。现在需要做js的UI监控界面,监控游戏的支付情况。要求按平台,游戏区分。如下图所示:其中圆形泡泡的大小代表支付额的大小。关系是:总的 = 各个平台相加的和。平台的和等于各个游戏的支付和。
数据可以从后台取到。并且当有新的支付行为发生时,相应平台的响应泡泡变大,与此同时平台的泡泡和总的泡泡也要变大。
最终的监控UI界面如图所示(仅是示意图,有待优化)。没有做过Js UI方面的编码。想请教下大大们:1.数据结构应该怎样设计才能满足需求(平台和游戏都是可能变动的)2.如何设计UI。是否有可以参考的成品或者框架。谢谢大家了。希望大大们都给点建议。灰常感激。

解决方案 »

  1.   

    我觉得用flash比较好一点 或者sl
      

  2.   

    感谢各位的回复。最终选择使用SVG来完成相应的功能。
    做的不是很完美,还有很多部分正在优化中:
    现分享出来,如果能给大家带来一丝丝帮助,不胜欣慰。源码如下:1.test.svg:<?xml version="1.0" encoding="UTF-8"?>
    <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload = "init(evt)">
    <script type="text/javascript" xlink:href="test.js"></script>
    </svg>2.test.js:var data = {
        facebook:{
            total:1500,
            titan:700,
            fishbowl:500,
            athena:400,
            bossv:500,
            dream:600
        },
        mixi:{
            total:1000,
            titan:500,
            fishbowl:400,
            athena:500,
            bossv:500,
            dream:600
        },
        kaixin:{
            total:1000,
            titan:300,
            fishbowl:400,
            athena:400,
            bossv:400,
            dream:400
        },
        renren:{
            total:900,
            titan:300,
            fishbowl:400,
            athena:600,
            bossv:600,
            dream:400
        },
        netlog:{
            total:1000,
            titan:300,
            fishbowl:400,
            athena:500,
            bossv:500,
            dream:400
        },
        minik:{
            total:1100,
            titan:300,
            fishbowl:400,
            athena:500,
            bossv:300,
            dream:400
        },
        daum:{
            total:1400,
            titan:300,
            fishbowl:400,
            athena:600,
            bossv:500,
            dream:400
        },
        tencent:{
            total:1200,
            titan:300,
            fishbowl:400,
            athena:560,
            bossv:600,
            dream:400
        }
    };var color = {
        facebook:{
            stroke: "red",
            filledColor: "red"
        },
        mixi:{
            stroke: "#FF9FFF",
            filledColor: "#FF9FFF"
        },
        kaixin:{
            stroke: "#FFBF02",
            filledColor: "#FFBF02"
        },
        renren:{
            stroke: "#836FFF",
            filledColor: "#836FFF"
        },
        netlog:{
            stroke: "#48D1CC",
            filledColor: "#48D1CC"
        },
        minik:{
            stroke: "#00CED1",
            filledColor: "#00CED1"
        },
        daum:{
            stroke: "#008B00",
            filledColor: "#008B00"
        },
        tencent:{
            stroke: "#A4D3EE",
            filledColor: "#A4D3EE"
        }
    };var svgns = "http://www.w3.org/2000/svg";/*
     *根据相应的支付额,获取应该显示的圆的半径大小
     */
    function getRadius(payment){
        var pay = parseInt(payment);
        return parseInt(pay/30);//待修改
    }function getMax(json){
        var max = 0;
        for( var val in json ){
            if(val > max){
                max = val;
            }
        }
        return max;
    }function getXY(preXY,space,radius,maxRadius){
        return preXY + space * 2 + radius + maxRadius;
    }/* draw svg cicle and append it to the svgDom */
    function drawCircle(evt,rx,ry,radius,stroke,filledColor){
        if ( window.svgDocument == null ){
            svgDocument = evt.target.ownerDocument;
        }
        var shape = svgDocument.createElementNS(svgns, "circle");
        shape.setAttributeNS(null,"cx",rx);
        shape.setAttributeNS(null,"cy",ry);
        shape.setAttributeNS(null,"r",radius);
        shape.setAttributeNS(null,"stroke",stroke);
        shape.setAttributeNS(null,"fill",filledColor);
        svgDocument.documentElement.appendChild(shape);
    }/* draw svg line and append it to the svgDom */
    function drawLine(evt,srcX,srcY,disX,disY,stroke){
        if ( window.svgDocument == null ){
            svgDocument = evt.target.ownerDocument;
        }
        var shape = svgDocument.createElementNS(svgns, "line");
        shape.setAttributeNS(null,"x1",srcX);
        shape.setAttributeNS(null,"y1",srcY);
        shape.setAttributeNS(null,"x2",disX);
        shape.setAttributeNS(null,"y2",disY);
        shape.setAttributeNS(null,"stroke",stroke);
        svgDocument.documentElement.appendChild(shape);
    }/* draw svg textNode and append it to the svgDom */
    function drawText(evt,rx,ry,radius,content){
        var fontSize = getFontSize(radius);
        if ( window.svgDocument == null ){
            svgDocument = evt.target.ownerDocument;
        }
        var shape = svgDocument.createElementNS(svgns, "text");
        shape.setAttributeNS(null,"x",rx);
        shape.setAttributeNS(null,"y",ry);
        shape.setAttributeNS(null,"font-size",fontSize);
        shape.textContent = content;
        svgDocument.documentElement.appendChild(shape);
    }/*
     * 根据半径和最大外围半径以及空隙space。求出可用的坐标。为均匀分配,这里采用平均分配的方式。
     * result = [{"x":10,y:20},{"x":40,y:60},{"x":70,y:80},{"x":40,y:60}];
     * */
    function getCorFromRadius(rx,ry,radius,space,maxRadius,sum){
        var result = new Array();
        var r = radius + space + maxRadius;//外部圆的最大半径
        var x0 = rx;
        var y0 = ry - r;
        result.push({"x":x0,"y":y0});
        var step = (360/sum) * Math.PI /180;//弧度
        var start = step;
        for(var i = 0;i < sum - 1;i++){
            var rxi = parseInt(rx + r * Math.sin(start));
            var ryi = parseInt(ry - r * Math.cos(start));
            result.push({"x":rxi,"y":ryi});
            start += step;
        }
        return result;
    }   /*
        *根据半径获取相应的字体大小,待优化。
        * */
    function getFontSize(radius){
        return parseInt(radius/1.5);
    }/* draw the total platform Map circly */
    function drawPlatformCircle(evt,platCount,gameCount){
        var rx = 900;
        var ry = 450;
        var radius = 200;
        var space = 30;
        var max = 70;
        var res = getCorFromRadius(rx, ry, radius, space, max, platCount);
        var i = 0;    for(var platform in data){
            var rx0 = res[i].x;
            var ry0 = res[i].y;
            var max = getMax(data[platform]);
            var stroke = color[platform].stroke;
            var filledColor = color[platform].filledColor;
            var max = getMax(data[platform]);
            var radius = getRadius(data[platform].total);//平台圆半径
            drawCircle(evt,rx0, ry0, radius, stroke, filledColor);
            var j = 0;
            for (var obj in data[platform]) {
                if (obj != "total") {
                    var rest = getCorFromRadius(rx0, ry0, radius, space, max, gameCount);
                    var outerX = rest[j].x;
                    var outerY = rest[j].y;
                    var outerRadius = getRadius(data[platform][obj]);
                    drawCircle(evt,outerX, outerY, outerRadius, stroke, filledColor);
                    drawLine(evt,rx0,ry0,outerX,outerY,stroke);
                    drawText(evt,outerX - outerRadius/2, outerY, outerRadius, obj);
                    j++;
                }
            }
            drawText(evt,rx0 - radius/2, ry0, radius, platform);
            i++;
        }
    }
    /* draw the total platform Map in line */
    function drawLinePlatform(evt){
        var rightIndex = 80;
        var top = 50;
        var space = 40;
        var count = 0;
        var maxTotalGame = 5;    for( var platform in data ){
            count ++;
            var stroke = color[platform].stroke;
            var filledColor = color[platform].filledColor;
            var max = getMax(data[platform]);
            var radius = getRadius(data[platform].total);//平台圆半径
            var rx = getXY(rightIndex,space,radius,max);//平台圆x轴坐标
            var ry = getXY(top,space,radius,max);//平台圆y轴坐标
            drawCircle(evt,rx,ry,radius,stroke,filledColor);
            var j = 0;
            for(var obj in data[platform]){
                if(obj != "total"){
                    var res = getCorFromRadius(rx,ry,radius,space,max,maxTotalGame);
                    var outerX = res[j].x;
                    var outerY = res[j].y;
                    var outerRadius = getRadius(data[platform][obj]);
                    drawLine(evt,rx,ry,outerX,outerY,stroke);
                    drawCircle(evt,outerX,outerY,outerRadius,stroke,filledColor);
                    drawText(evt,outerX - outerRadius/2,outerY,outerRadius,obj);
                    j++;
                }
            }
            drawText(evt,rx - radius/2,ry,radius,platform);
            rightIndex = (rx + radius + space * 2 + max);
            if(count % 5 == 0){
                rightIndex = 120;
                top = (ry + radius + space + max)+50;//TODO:这个有问题,没有考虑本身的高度
            }
        }
    }function init(evt){
        drawPlatformCircle(evt,8,5);
    }