首页 > 代码库 > (二)联动的饼图与柱形图

(二)联动的饼图与柱形图

1.  前言

 

2.  联动的饼图与柱形图

图: 技术分享

本地链接:http://127.0.0.1/Example/case4/pie-bar.html

知识点:

技术分享
  1 <!DOCTYPE html>
  2 <meta charset="utf-8">
  3 <style>
  4 body{
  5     width:1060px;
  6     margin:50px auto;
  7 }
  8 path {  stroke: #fff; }
  9 path:hover {  opacity:0.9; }
 10 rect:hover {  fill:blue; }
 11 .axis {  font: 10px sans-serif; }
 12 .legend tr{    border-bottom:1px solid grey; }
 13 .legend tr:first-child{    border-top:1px solid grey; }
 14 
 15 .axis path,
 16 .axis line {
 17   fill: none;
 18   stroke: #000;
 19   shape-rendering: crispEdges;
 20 }
 21 
 22 .x.axis path {  display: none; }
 23 .legend{
 24     margin-bottom:76px;
 25     display:inline-block;
 26     border-collapse: collapse;
 27     border-spacing: 0px;
 28 }
 29 .legend td{
 30     padding:4px 5px;
 31     vertical-align:bottom;
 32 }
 33 .legendFreq, .legendPerc{
 34     align:right;
 35     width:50px;
 36 }
 37 
 38 </style>
 39 <body>
 40 <div id=‘dashboard‘>
 41 </div>
 42 <script src="http://d3js.org/d3.v3.min.js"></script>
 43 <script>
 44 function dashboard(id, fData){
 45     var barColor = steelblue;
 46     function segColor(c){ return {low:"#807dba", mid:"#e08214",high:"#41ab5d"}[c]; }
 47 
 48     // compute total for each state.
 49     fData.forEach(function(d){d.total=d.freq.low+d.freq.mid+d.freq.high;});
 50 
 51     // function to handle histogram.
 52     function histoGram(fD){
 53         var hG={},    hGDim = {t: 60, r: 0, b: 30, l: 0};
 54         hGDim.w = 500 - hGDim.l - hGDim.r,
 55         hGDim.h = 300 - hGDim.t - hGDim.b;
 56 
 57         //create svg for histogram.
 58         var hGsvg = d3.select(id).append("svg")
 59             .attr("width", hGDim.w + hGDim.l + hGDim.r)
 60             .attr("height", hGDim.h + hGDim.t + hGDim.b).append("g")
 61             .attr("transform", "translate(" + hGDim.l + "," + hGDim.t + ")");
 62 
 63         // create function for x-axis mapping.
 64         var x = d3.scale.ordinal().rangeRoundBands([0, hGDim.w], 0.1)
 65                 .domain(fD.map(function(d) { return d[0]; }));
 66 
 67         // Add x-axis to the histogram svg.
 68         hGsvg.append("g").attr("class", "x axis")
 69             .attr("transform", "translate(0," + hGDim.h + ")")
 70             .call(d3.svg.axis().scale(x).orient("bottom"));
 71 
 72         // Create function for y-axis map.
 73         var y = d3.scale.linear().range([hGDim.h, 0])
 74                 .domain([0, d3.max(fD, function(d) { return d[1]; })]);
 75 
 76         // Create bars for histogram to contain rectangles and freq labels.
 77         var bars = hGsvg.selectAll(".bar").data(fD).enter()
 78                 .append("g").attr("class", "bar");
 79 
 80         //create the rectangles.
 81         bars.append("rect")
 82             .attr("x", function(d) { return x(d[0]); })
 83             .attr("y", function(d) { return y(d[1]); })
 84             .attr("width", x.rangeBand())
 85             .attr("height", function(d) { return hGDim.h - y(d[1]); })
 86             .attr(fill,barColor)
 87             .on("mouseover",mouseover)// mouseover is defined below.
 88             .on("mouseout",mouseout);// mouseout is defined below.
 89 
 90         //Create the frequency labels above the rectangles.
 91         bars.append("text").text(function(d){ return d3.format(",")(d[1])})
 92             .attr("x", function(d) { return x(d[0])+x.rangeBand()/2; })
 93             .attr("y", function(d) { return y(d[1])-5; })
 94             .attr("text-anchor", "middle");
 95 
 96         function mouseover(d){  // utility function to be called on mouseover.
 97             // filter for selected state.
 98             var st = fData.filter(function(s){ return s.State == d[0];})[0],
 99                 nD = d3.keys(st.freq).map(function(s){ return {type:s, freq:st.freq[s]};});
100 
101             // call update functions of pie-chart and legend.
102             pC.update(nD);
103             leg.update(nD);
104         }
105 
106         function mouseout(d){    // utility function to be called on mouseout.
107             // reset the pie-chart and legend.
108             pC.update(tF);
109             leg.update(tF);
110         }
111 
112         // create function to update the bars. This will be used by pie-chart.
113         hG.update = function(nD, color){
114             // update the domain of the y-axis map to reflect change in frequencies.
115             y.domain([0, d3.max(nD, function(d) { return d[1]; })]);
116 
117             // Attach the new data to the bars.
118             var bars = hGsvg.selectAll(".bar").data(nD);
119 
120             // transition the height and color of rectangles.
121             bars.select("rect").transition().duration(500)
122                 .attr("y", function(d) {return y(d[1]); })
123                 .attr("height", function(d) { return hGDim.h - y(d[1]); })
124                 .attr("fill", color);
125 
126             // transition the frequency labels location and change value.
127             bars.select("text").transition().duration(500)
128                 .text(function(d){ return d3.format(",")(d[1])})
129                 .attr("y", function(d) {return y(d[1])-5; });
130         }
131         return hG;
132     }
133 
134     // function to handle pieChart.
135     function pieChart(pD){
136         var pC ={},    pieDim ={w:250, h: 250};
137         pieDim.r = Math.min(pieDim.w, pieDim.h) / 2;
138 
139         // create svg for pie chart.
140         var piesvg = d3.select(id).append("svg")
141             .attr("width", pieDim.w).attr("height", pieDim.h).append("g")
142             .attr("transform", "translate("+pieDim.w/2+","+pieDim.h/2+")");
143 
144         // create function to draw the arcs of the pie slices.
145         var arc = d3.svg.arc().outerRadius(pieDim.r - 10).innerRadius(0);
146 
147         // create a function to compute the pie slice angles.
148         var pie = d3.layout.pie().sort(null).value(function(d) { return d.freq; });
149 
150         // Draw the pie slices.
151         piesvg.selectAll("path").data(pie(pD)).enter().append("path").attr("d", arc)
152             .each(function(d) { this._current = d; })
153             .style("fill", function(d) { return segColor(d.data.type); })
154             .on("mouseover",mouseover).on("mouseout",mouseout);
155 
156         // create function to update pie-chart. This will be used by histogram.
157         pC.update = function(nD){
158             piesvg.selectAll("path").data(pie(nD)).transition().duration(500)
159                 .attrTween("d", arcTween);
160         }
161         // Utility function to be called on mouseover a pie slice.
162         function mouseover(d){
163             // call the update function of histogram with new data.
164             hG.update(fData.map(function(v){
165                 return [v.State,v.freq[d.data.type]];}),segColor(d.data.type));
166         }
167         //Utility function to be called on mouseout a pie slice.
168         function mouseout(d){
169             // call the update function of histogram with all data.
170             hG.update(fData.map(function(v){
171                 return [v.State,v.total];}), barColor);
172         }
173         // Animating the pie-slice requiring a custom function which specifies
174         // how the intermediate paths should be drawn.
175         function arcTween(a) {
176             var i = d3.interpolate(this._current, a);
177             this._current = i(0);
178             return function(t) { return arc(i(t));    };
179         }
180         return pC;
181     }
182 
183     // function to handle legend.
184     function legend(lD){
185         var leg = {};
186 
187         // create table for legend.
188         var legend = d3.select(id).append("table").attr(class,legend);
189 
190         // create one row per segment.
191         var tr = legend.append("tbody").selectAll("tr").data(lD).enter().append("tr");
192 
193         // create the first column for each segment.
194         tr.append("td").append("svg").attr("width", 16).attr("height", 16).append("rect")
195             .attr("width", 16).attr("height", 16)
196             .attr("fill",function(d){ return segColor(d.type); });
197 
198         // create the second column for each segment.
199         tr.append("td").text(function(d){ return d.type;});
200 
201         // create the third column for each segment.
202         tr.append("td").attr("class",legendFreq)
203             .text(function(d){ return d3.format(",")(d.freq);});
204 
205         // create the fourth column for each segment.
206         tr.append("td").attr("class",legendPerc)
207             .text(function(d){ return getLegend(d,lD);});
208 
209         // Utility function to be used to update the legend.
210         leg.update = function(nD){
211             // update the data attached to the row elements.
212             var l = legend.select("tbody").selectAll("tr").data(nD);
213 
214             // update the frequencies.
215             l.select(".legendFreq").text(function(d){ return d3.format(",")(d.freq);});
216 
217             // update the percentage column.
218             l.select(".legendPerc").text(function(d){ return getLegend(d,nD);});
219         }
220 
221         function getLegend(d,aD){ // Utility function to compute percentage.
222             return d3.format("%")(d.freq/d3.sum(aD.map(function(v){ return v.freq; })));
223         }
224 
225         return leg;
226     }
227 
228     // calculate total frequency by segment for all state.
229     var tF = [low,mid,high].map(function(d){
230         return {type:d, freq: d3.sum(fData.map(function(t){ return t.freq[d];}))};
231     });
232 
233     // calculate total frequency by state for all segment.
234     var sF = fData.map(function(d){return [d.State,d.total];});
235 
236     var hG = histoGram(sF), // create the histogram.
237         pC = pieChart(tF), // create the pie-chart.
238         leg= legend(tF);  // create the legend.
239 }
240 </script>
241 
242 <script>
243 var freqData=[
244 {State:AL,freq:{low:4786, mid:1319, high:249}}
245 ,{State:AZ,freq:{low:1101, mid:412, high:674}}
246 ,{State:CT,freq:{low:932, mid:2149, high:418}}
247 ,{State:DE,freq:{low:832, mid:1152, high:1862}}
248 ,{State:FL,freq:{low:4481, mid:3304, high:948}}
249 ,{State:GA,freq:{low:1619, mid:167, high:1063}}
250 ,{State:IA,freq:{low:1819, mid:247, high:1203}}
251 ,{State:IL,freq:{low:4498, mid:3852, high:942}}
252 ,{State:IN,freq:{low:797, mid:1849, high:1534}}
253 ,{State:KS,freq:{low:162, mid:379, high:471}}
254 ];
255 
256 dashboard(#dashboard,freqData);
257 </script>
View Code

 

(二)联动的饼图与柱形图