D3.js流程图转换没有任何内容

时间:2014-06-10 21:03:02

标签: javascript d3.js

另一个D3.js noob在这里。

我开始编辑来自http://bl.ocks.org/mbostock/4060954的库存流图示例。

我看过几个类似的问题,例如thisthisthis,但我似乎无法找到我的错误。

我有两个json模拟数据,layers0和layers1(源自上面的一个示例,来自this fiddle)。通过更改我的数据,我可以毫无问题地绘制这两个:

svg.selectAll("path")
    .data(layers0/1)  #layers0 or layers1, both work
.enter().append("path")
    .attr("d", function(d) { return area(d.values); })
    .style("fill", function() { return color(Math.random()); });

然而,当我尝试在这两个图之间创建一个过渡时,原始图消失了,我留下了一个空的空间:

function transition() {
d3.selectAll("path")
    .data(layers1/0)  #the alternate (or same) one from the function above
    .transition()
    .duration(500)
    .attr("d", area);
}

最终我想要很多按钮,而transition应该在它们之间移动,例如在this example中,但是现在我只想在两个数据集之间移动。

2 个答案:

答案 0 :(得分:2)

好吧,我找到了一个有效的解决方案,尽管我还没有完全理解它。解决方案主要是从this fiddle复制的。我将指出示例代码和必须提供的代码之间的差异(如果有人可以解释为什么,这将是很好的)它的工作。

我会发布我的整个代码给任何发现D3令人困惑的新手。

HTML:(我正在处理金字塔应用程序,因此脚本会在头部导入)

<head>
<title>           
    Graph
</title>

    <link rel="stylesheet" type="text/css" href="${request.static_url('monitor:static/css/graph.css')}"/>

    <script type="text/javascript" src="${request.static_url('monitor:static/jquery-ui-1.10.3/jquery-1.9.1.js')}"></script>
    <script type="text/javascript" src="${request.static_url('monitor:static/jquery-ui-1.10.3/ui/jquery-ui.js')}"></script>
    <script type="text/javascript" src="${request.static_url('monitor:static/D3/d3.min.js')}"></script>
    <script type="text/javascript" src="${request.static_url('monitor:static/js/graph.js')}"></script>
</head>

<body>
    <body onload="graphplot()">
    <h4 id="Heading">Streamgraph</h4>
    <div id="graph_area"></div>
</body>

然后这是我的graph.js:

function graphplot(){


test_data0 = [{"0": 0.2, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.6, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.6}, {"0": 0.3, "1": 0.0, "-1": 0.1}, {"0": 0.0, "1": 0.2, "-1": 0.3}, {"0": 0.3, "1": 0.5, "-1": 0.0}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}]
test_data1 = [{"0": 0.0, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.6, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.6}, {"0": 0.3, "1": 0.3, "-1": 0.0}, {"0": 0.0, "1": 0.3, "-1": 0.3}, {"0": 0.3, "1": 0.1, "-1": 0.6}, {"0": 0.3, "1": 0.0, "-1": 0.0}, {"0": 0.0, "1": 0.0, "-1": 0.0}]


    var width = $("#graph_area").width(),
        height = 500;


    var toggle = 0;  //just so that the animation toggles between these two data

    $("#graph_area").click(function(){
        console.log('test')

        if (toggle == 0){
            streamed_history(test_data1)
            toggle = 1;
        }else {
            streamed_history(test_data0)
            toggle=0;
        }
    });


    var colors = {'0': '#6ff500', '1': '#ffad0a', '-1': '#f90035'}, //colours for the three layers; no longer random
        feedbacks = [-1, 0, 1],
        stack = d3.layout.stack().offset("wiggle"); //the plot sits on its base without wiggle
        //.values(function(d) { return d.values; }); --->removed. Throws: TypeError: t is undefined

    var svg = d3.select("#graph_area").append("svg")
        .attr("width", width)
        .attr("height", height);



    streamed_history(test_data0)

    function streamed_history(data) {
        data_array = feedbacks.map(function (f) {
            return data.map(function(element, i) { return {x: i, y: element[f]}; })
        }),
        layers = stack(data_array)  //--->No nest.entries.  And the below code for only one layers variable
        layers = feedbacks.map(function (f, i) {
            return {layer: layers[i], feedback: f, color: colors[f]}
        })



        var x = d3.scale.linear()
            .domain([0, data.length - 1])
            .range([0, width]);

        var y = d3.scale.linear()
            .domain([0,1])  //--->coplicated thing removed.  It just needs to be:([0, max of data])
            .range([height, 0]);

        var area = d3.svg.area().interpolate("basis")
            .x(function(d) { return x(d.x); })
            .y0(function(d) { return y(d.y0); })
            .y1(function(d) { return y(d.y0 + d.y); });

        //enter
        svg.selectAll("path")
            .data(layers)
        .enter().append("path")
            .attr("d", function (d) {return area(d.layer);})
            .style("fill", function(d) { return d.color; });

        //update
        d3.selectAll("path") //this effectively replaces transition(), since now each dataset is plotted independently with the duration of transition defined here.
        .data(layers)
        .transition()
        .duration(500)
        .attr("d", function (d) {return area(d.layer);});
    }

}//end graphplot

graphplot()

希望这有助于将来的任何人!

答案 1 :(得分:0)

我试图重现你在这里要求的内容:

http://jsfiddle.net/g9JNH/

<button class="button1" onclick="transition()">Transition 1</button>
<button class="button2" onclick="transition2()">Transition 2</button>
<script>
var n = 20, // number of layers
    m = 200, // number of samples per layer
    stack = d3.layout.stack().offset("wiggle"),
    layers0 = stack(d3.range(n).map(function() { return bumpLayer(m); })),
    layers1 = stack(d3.range(n).map(function() { return bumpLayer(m); }));

    var width = 960,
    height = 500;

    var x = d3.scale.linear()
        .domain([0, m - 1])
        .range([0, width]);

    var y = d3.scale.linear()
       .domain([0, d3.max(layers0.concat(layers1), function(layer) { 
            return d3.max(layer, function(d) { return d.y0 + d.y; }); })])
       .range([height, 0]);

    var color = d3.scale.linear()
       .range(["#aad", "#556"]);

    var area = d3.svg.area()
       .x(function(d) { return x(d.x); })
       .y0(function(d) { return y(d.y0); })
       .y1(function(d) { return y(d.y0 + d.y); });

    var svg = d3.select("body").append("svg")
       .attr("width", width)
       .attr("height", height);

    svg.selectAll("path")
       .data(layers0)
       .enter().append("path")
       .attr("d", area)
       .style("fill", function() { return color(Math.random()); });

    function transition() {
       d3.selectAll("path")
           .data(layers1)
           .transition()
           .duration(2500)
           .attr("d", area);
    }

    function transition2() {
        d3.selectAll("path")
           .data(layers0)
           .transition()
           .duration(2500)
           .attr("d", area);
    }

    // Inspired by Lee Byron's test data generator.
    function bumpLayer(n) {

         function bump(a) {
             var x = 1 / (.1 + Math.random()),
             y = 2 * Math.random() - .5,
             z = 10 / (.1 + Math.random());
             for (var i = 0; i < n; i++) {
                 var w = (i / n - y) * z;
                 a[i] += x * Math.exp(-w * w);
             }
         }

         var a = [], i;
         for (i = 0; i < n; ++i) a[i] = 0;
         for (i = 0; i < 5; ++i) bump(a);
         return a.map(function(d, i) { return {x: i, y: Math.max(0, d)}; });
    }
    </script>

我使用了相同的示例,并且代码原则上有效,可能还有其他一些你已经实现的东西,比如更多的html,或者数据集中有些错误?或者我可能没有理解你的问题...