d3.js dougnut饼图的动画

时间:2017-03-29 14:55:26

标签: javascript d3.js

我正在开发一个应用程序,它将是一个混合饼图和气泡图 - enter image description here 这是一个简单的甜甜饼饼图的工作动画。

http://jsfiddle.net/Qh9X5/8817/

var width = 960,
    height = 500,
    radius = Math.min(width, height) / 2;

var color = d3.scale.ordinal()
    .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);

var arc = d3.svg.arc()
    .outerRadius(radius - 60)
    .innerRadius(radius - 70);

var pie = d3.layout.pie()
    .sort(null)
    .value(function(d) { return d.value; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");


  var data = [
    {
      "group": "<5",
      "value": 1000,
      "children": [
        {
          "group": "<5",     
          "label": "Mel",
          "value": 1000,
          "totalGroupValue": 1000
        }
      ]
    },
    {
      "group": "5-13",
      "value": 1000,
      "children": [
        {
          "group": "5-13",        
          "label": "Erica",
          "value": 1000,
          "totalGroupValue": 1000
        }
      ]
    },
    {
      "group": "14-17",
      "value": 2000,
      "children": [
        {
          "group": "14-17",
          "label": "Jessica",
          "value": 1500,
          "totalGroupValue": 2000  
        },
        {
          "group": "14-17",
          "label": "Jill",
          "value": 500,
          "totalGroupValue": 2000  
        }
      ]
    },
    {
      "group": "18-24",
      "value": 1300,
      "children": [
        {
          "group": "18-24",
          "label": "Jerry",
          "value": 500,          
          "totalGroupValue": 1300 
        },
        {
          "group": "18-24",
          "label": "Ben",
          "value": 500,
          "totalGroupValue": 1300  
        },
        {
          "group": "18-24",
          "label": "Billy",
          "value": 300,
          "totalGroupValue": 1300  
        }
      ]
    },
    {
      "group": "25-44",
      "value": 1000,
      "children": [
        {
          "group": "25-44",
          "label": "Kelly",
          "value": 1000,
          "totalGroupValue": 1000
        }
      ]
    }
  ];  


  var g = svg.selectAll(".arc")
      .data(pie(data))
    .enter().append("g")
      .attr("class", "arc");

  g.append("path")
      .attr("d", arc)
      .style("fill", function(d) {
        return color(d.data.group); 
      });

  arc
    .outerRadius(radius - 10)
    .innerRadius(0);


//create zone regions

var zones = [];
g.append("circle")
  .attr("transform", function(d) {
        zones[d.data.group] = arc.centroid(d);
    return "translate(" + arc.centroid(d) + ")"; 
  })
  .attr("r", "1px")
  .style("fill", function(d) { 
    return "black"//color(d.data.group); 
  });

 g.append("g")
    .attr("class", function(d,i) { 
    console.log("d", d)
    return "bubble"+i;//color(d.data.group); 
  })
  .attr("transform", function(d) {
        zones[d.data.group] = arc.centroid(d);
    return "translate(" + arc.centroid(d) + ")"; 
  })
  .attr("r", "1px")
  .style("fill", function(d) { 
    return "black"//color(d.data.group); 
  });


//create zone regions


//custom bubble chart
function makeBubbles(transform, group, radius){
    g.append("circle")
    .attr("transform", function(d) {
      return "translate("+transform+")"; 
    })
    .attr("r", radius)
    .style("stroke", function(d) { 
      return "black";//color(group); 
    })
    .style("fill", function(d) { 
      return color(group); 
    });
}


            function bubbledata(data){
      console.log("data", data)
                //loop through data -- and MERGE children
                var childs = [];
                $.each(data, function( index, value ) {
                    childs.push(value.children);                    
                });
                var merged = data;//[].concat.apply([], childs);//flatterns multidimensional array

                return $.extend(true, {}, {"children": merged});// return deep clone
            }


function setBubbleChart(width, index, data){

                  //_create bubble
                    var diameter = width/2;//take half/width

                    var bubs = svg.select(".bubble"+index).append("g")
                            .attr("class", "bubs");

                    bubs.attr("transform", "translate("+-diameter/2+","+-diameter/2+")");

                    var bubble = d3.layout.pack()
                      .size([diameter, diameter])
                      .value(function(d) {
                        return d.value;
                      })
                      .padding(3);

                  //_create bubble
          var data = bubbledata(data);

                        var nodes = bubble.nodes(data)
                          .filter(function(d) {
                             return !d.children;
                          }); // filter out the outer bubble


                        var bubbles = bubs.selectAll('circle')
                          .data(nodes);


                bubbles.enter()
                    .insert("circle")
                    .attr('transform', function (d) {
                        return 'translate(' + d.x + ',' + d.y + ')';
                    })
                    .attr('r', function (d) {
                        return d.r;
                    })
                    .style("fill", function (d) {
return color(d.group);
                    });

                bubbles = bubbles.transition()
                    .transition()
                    .duration(250)
                    .attr('transform', function(d) {
                        return 'translate(' + d.x + ',' + d.y + ')';
                    })
                    .attr('r', function (d) {
                        return d.r;
                    })
                    .ease('sine');

}



//loop through data and for EACH children array paint dots.
$.each(data, function( index, value ) {
setBubbleChart(100, index, value.children);


});    
//custom bubble chart    


function type(d) {
  d.value = +d.value;
  return d;
}

enter image description here http://jsfiddle.net/NYEaX/1487/ 这是一个静态圆环图 - 我计算了中弧 - 但已经丢失了动画。所以使用上面的代码示例 - 在哪里可以获得arc.centroid(d)?

ModalService.showModal({
        templateUrl: 'newProject.html',
        controller: "NewProjectModalController"
    }).then(function(modal) {
        modal.element.modal();
        modal.close.then(function(result) {
            $('#newProjectModal').modal('hide');
            $('body').removeClass('modal-open');
            $('.modal-backdrop').remove();
        }
        // added by me
        modal.element.on('hidden.bs.modal', function () {// bootstrap event
            modal.scope.close(false,500);
        });
    });
});

1 个答案:

答案 0 :(得分:0)

我已经绘制了中弧 - 但他们没有更新数据?

enter image description here http://jsfiddle.net/Qh9X5/10066/

>>> import pdfrw

>>> file_object = pdfrw.PdfReader("Hello.pdf")
>>> file_object
{'/ID': ['<f643bc0910dfb67725d53e11054f4609>', '<f643bc0910dfb67725d53e11054f4609>'], '/Info': (5, 0), '/Root': {'/Outl
ines': (8, 0), '/PageMode': '/UseNone', '/Pages': {'/Count': '1', '/Kids': [{'/Contents': (7, 0), '/MediaBox': ['0', '0
', '595.2756', '841.8898'], '/Parent': {...}, '/Resources': {'/Font': (1, 0), '/ProcSet': ['/PDF', '/Text', '/ImageB',
'/ImageC', '/ImageI']}, '/Rotate': '0', '/Trans': {}, '/Type': '/Page'}], '/Type': '/Pages'}, '/Type': '/Catalog'}, '/S
ize': '9'}

>>> file_object.pages[0]
{'/Contents': (7, 0), '/MediaBox': ['0', '0', '595.2756', '841.8898'], '/Parent': {'/Count': '1', '/Kids': [{...}], '/T
ype': '/Pages'}, '/Resources': {'/Font': (1, 0), '/ProcSet': ['/PDF', '/Text', '/ImageB', '/ImageC', '/ImageI']}, '/Rot
ate': '0', '/Trans': {}, '/Type': '/Page'}

>>> file_object.pages[0].keys()
['/Contents', '/MediaBox', '/Parent', '/Resources', '/Rotate', '/Trans', '/Type']

>>> file_object.pages[0].Contents
{'/Filter': ['/ASCII85Decode', '/FlateDecode'], '/Length': '102'}

>>> file_object.pages[0].Contents.stream
'GapQh0E=F,0U\\H3T\\pNYT^QKk?tc>IP,;W#U1^23ihPEM_?CW4KISi90EC-p>QkRte=<%V"lI7]P)Rn29neZ[Kb,htEWn&q7Q2"V~>'

enter image description here

我设法创建了一个arc2 - 并为占位符设置了动画。

http://jsfiddle.net/Qh9X5/10068/

function change(data) {


  var slice = svg.select(".slices").selectAll("path.slice")
    .data(pie(data), key);

  slice.enter()
    .insert("path")
    .style("fill", function(d) {
      return color(d.data.label);
    })
    .attr("class", "slice");

  slice
    .transition().duration(1000)
    .attrTween("d", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        return arc(interpolate(t));
      };
    })

  slice.exit()
    .remove();



  var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
    .data(pie(data), key);

  placeholders.enter()
    .insert("circle")
    .style("fill", function(d) {
      return "white";
      //return color(d.data.label); 
    })
    .attr("transform", function(d) {
      return "translate(" + arc.centroid(d) + ")";
    })
    .attr("r", "5")
    .attr("class", "placeholder");

  placeholders
    .transition().duration(1000)

  placeholders.exit()
    .remove();   


};

enter image description here

http://jsfiddle.net/Qh9X5/10075/

我设法将饼图与气泡图合并 - 如果数据集发生变化 - 动画应该是稳定的。

var svg = d3.select("#pies")
  .append("svg")
  .append("g")

svg.append("g")
  .attr("class", "slices");
svg.append("g")
  .attr("class", "placeholders");
svg.append("g")
  .attr("class", "labels");
svg.append("g")
  .attr("class", "lines");

var width = 560,
  height = 450,
  radius = Math.min(width, height) / 2;

var pie = d3.layout.pie()
  .sort(null)
  .value(function(d) {
    return d.value;
  });

var arc = d3.svg.arc()
  .outerRadius(radius * 0.85)
  .innerRadius(radius * 0.83);

var arc2 = d3.svg.arc()
    .outerRadius(radius - 10)
    .innerRadius(0);


var outerArc = d3.svg.arc()
  .innerRadius(radius * 0.9)
  .outerRadius(radius * 0.9);

svg.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var key = function(d) {
  return d.data.label;
};

var color = d3.scale.ordinal()
  .domain(["Lorem ipsum", "dolor sit", "amet", "consectetur", "adipisicing"])
  .range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56"]);

function randomData() {
  var labels = color.domain();
  return labels.map(function(label) {
    return {
      label: label,
      value: Math.random()
    }
  });
}


console.log("randomData()", randomData());
change(randomData());

d3.select(".randomize")
  .on("click", function() {
    change(randomData());
  });


function change(data) {



  var slice = svg.select(".slices").selectAll("path.slice")
    .data(pie(data), key);

  slice.enter()
    .insert("path")
    .style("fill", function(d) {
      return color(d.data.label);
    })
    .attr("class", "slice");

  slice
    .transition().duration(1000)
    .attrTween("d", function(d) {
      this._current = this._current || d;
      var interpolate = d3.interpolate(this._current, d);
      this._current = interpolate(0);
      return function(t) {
        return arc(interpolate(t));
      };
    })

  slice.exit()
    .remove();




  var placeholders = svg.select(".placeholders").selectAll("circle.placeholder")
    .data(pie(data), key);

  placeholders.enter()
    .insert("circle")
    .style("fill", function(d) {
      return "white";
    })
    .attr("r", "5")
    .attr("class", "placeholder");


  placeholders
    .transition().duration(1000)
    .attr("transform", function(d) {
        console.log("arc.centroid(d)", arc2.centroid(d))
      return "translate(" + arc2.centroid(d) + ")";
    })

  placeholders.exit()
    .remove();



};