D3-动态x y轴条形图轴

时间:2019-11-11 14:01:37

标签: javascript d3.js dynamic bar-chart

我正在尝试使用下面的网页制作一个动态图。

https://twitter.com/ThingsWork/status/1124378131328929792/video/1

我不太清楚如何定义问题。我对条的宽度没有问题,但是由于宽度的变化,所以订购它们的事实。

我已经意识到,在一个元素中,一次只能有一个活动过渡。现在我不知道如何继续。

有人可以让我知道制作此图形的步骤吗?我最大的问题是,考虑到x坐标必须不断更新,如何同时更新x和y轴上的条。

这是文件test.txt的内容

org jan19   feb19   mar19
9911-Org 1  4.14    8.54    11.54
9912-Org 2  7.51    5.51    9.51
9913-Org 3  10.36   22.36   15.36
9914-Org 4  4.65    8.65    8.65
9916-Org 5  1.54    1.54    1.54
9936-Org 6  13.02   13.02   13.02
9937-Org 7  61.92   41.92   55.92
9938-Org 8  3.95    3.95    3.95
9940-Org 9  15.08   15.08   15.08
9943-Org 10 10.60   10.60   10.60
9945-Org 11 5.83    5.83    5.83
9976-Org 12 36.29   45.29   45.29
    <!DOCTYPE html>
    <meta charset="utf-8">

    <!-- Load js library -->
    <script src="./libraries/d3/d3.js"></script>

    <style type="text/css">
      svg {border:1px solid #eb830d1f;}
    </style>

    <div id="d3_graph1"></div>


    <script>
      // Intervals
      var transition_value;
      var transition_interval;

      // Principal column name
      name_ppal_col = "org"

      // Dynamic columns names
      name_dinamic_cols = ["jan19", "feb19", "mar19"]


      // set the dimensions and margins of the graph
      var margin = {top: 20, right: 30, bottom: 40, left: 290},
          width = 660 - margin.left - margin.right,
          height = 400 - margin.top - margin.bottom;

      // append the svg object to the body of the page
      var svg = d3.select("#d3_graph1")
        .append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
        .append("g")
          .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");

      var actual_state;
      var idens;


      // Parse the Data
      d3.tsv("./data/test.txt").then(function(data) {

        // we order the first column from highest to lowest 
        if (data.length>=2) {
          data.sort(function (a, b) {
            return (b[name_dinamic_cols[0]]  - a[name_dinamic_cols[0]])
          })    
        }


        //  id - principal column asociation
        idens = new Object();
        for (i = 0; i < data.length; i++) {
          idens[data[i][name_ppal_col]] = i + 1;
        }


        // Add X axis
        var x = d3.scaleLinear()
          .domain([0, 70])
          .range([ 0, width]);

        svg.append("g")
          .attr("transform", "translate(0," + height + ")")
          .call(d3.axisBottom(x))      
          .selectAll("text")        
          .attr("transform", "translate(-10,0)rotate(-45)")
          .style("text-anchor", "end")
         ;

        // Y axis
        var y = d3.scaleBand()
          .range([ 0, height ])
          .domain(data.map(function(d) { return d[name_ppal_col]; }))
          .padding(.1);

        svg.append("g")
          .call(d3.axisLeft(y))


        //Bars
        svg.selectAll("myRect")
          .data(data)
          .enter()
          .append("rect")
          .attr("x", x(0))
          .attr("y", function(d) { return y(d[name_ppal_col]); })
          .attr("width", function(d) { return x(d[name_dinamic_cols[0]]); })
          .attr("height", y.bandwidth() )
          .attr("fill", "#FF9A00")
          .attr("value", function(d) { return d[name_dinamic_cols[0]]; })
          .attr("id", function(d) { return "rect" + idens[d[name_ppal_col]] ; })

        // Labels 
        svg.append("g")
          .attr("fill", "black")
          .attr("text-anchor", "end")
          .style("font", "12px sans-serif")
          .selectAll("text")
          .data(data)
          .join("text")
          .attr("x", d => x(d[name_dinamic_cols[0]]) + 35)
          .attr("y", d => y(d[name_ppal_col]) + y.bandwidth() / 2)
          .attr("dy", "0.35em")
          .attr("id", function(d) { return "label" + idens[d[name_ppal_col]];})
          .text(d => d[name_dinamic_cols[0]]);



        if (data.length > 2) {

          var n_transicion = 1;

          // we keep the order by identifier

          actual_state = [];

          d3.selectAll("#d3_graph1 rect").each(function(d,i) {
                                                id_actual = d3.select(this).attr("id");
                                                y_actual = d3.select(this).attr("y");
                                                // Quitamos la cadena rect
                                                id_actual = id_actual.slice(4,id_actual.length);                               
                                                actual_state[id_actual] = id_actual;
                                            }) 
                                            //console.log("orden",actual_state);


          function update_X() {

            for (j = 0; j < data.length; j++) {

                var rect = "#rect" + idens[(data[j][name_ppal_col])] 
                var label = "#label" + idens[(data[j][name_ppal_col])]



                // Bar
                d3.select(rect)
                .transition()
                .duration(3000)
                .attr("width", x(data[j][name_dinamic_cols[n_transicion]]))
                .attr("value", data[j][name_dinamic_cols[n_transicion]])


                // Label 
                n_transicion_ant = n_transicion - 1;
                n_transicion_act = n_transicion;

                d3.select(label)
                .transition()
                .duration(3000)
                .attr("x", d => x(d[name_dinamic_cols[n_transicion]]) + 35)
                .tween("text", function(d) {

                                  var i = d3.interpolate(d[name_dinamic_cols[(n_transicion_ant)]], d[name_dinamic_cols[n_transicion_act]]);
                                  return function(t) {
                                            d3.select(this).text(d3.format(",.2f")(i(t)));};
                });
            }
            n_transicion++;

          }  

          function update_Y() {

            //  el orden 
            values =  [];
            actual_state = [];

            // Sort values
            d3.selectAll("#d3_graph1 rect").each(function(d,i) {
                                                  id_actual = d3.select(this).attr("id");
                                                  valor_actual = d3.select(this).attr("value");

                                                  // Quitamos la cadena rect
                                                  id_actual = id_actual.slice(4,id_actual.length);
                                                  values[i] = {  id: parseInt(id_actual),
                                                                  value: valor_actual
                                                                };        
                                              }) 

            values.sort(function(a,b) {
              return (b.value  - a.value);    
            })

            pos = 0;  
            values.forEach(function (reg) {
                              actual_state[pos]= reg.id;
                              pos++;
                            }); 
            console.log("values:",values); 
            console.log("actual_state:",actual_state);


            data.sort(function(a,b) {
              index_a = idens[a.red];
              index_b = idens[b.red];

              //console.log("index_a:"+index_a);
              //console.log("index_b:"+index_b);
              //console.log("red:",a.red,"index_a:",index_a,"actual_state:",actual_state.indexOf(index_a));
              //console.log("red:",b.red,"index_b:",index_b,"actual_state:",actual_state.indexOf(index_b));

              return (actual_state.indexOf(index_b) - actual_state.indexOf(index_a));
            })
            console.log("data:",data);  

            // if do transition, stop the transition of X!! doesn't work. I don't know how to continue
          }  



          update_X();


          transition_value = d3.interval(function(interval) {
                                        if ((n_transicion < Object.keys(data[0]).length - 1)) {
                                          // axis X
                                          update_X();
                                        }
                                        else {

                                          transition_value.stop();
                                          transition_interval.stop();
                                        }
                                      }  , 3000); 

          // Axis y                             
          // every 200 ms we check if the order has changed
          transition_interval = d3.interval(function(interval) {
                                            update_Y();


                                          }, 200);  




        }  

      })

    </script>

0 个答案:

没有答案