2014-10-27 89 views
0

我正在開發一個圖例,使用此jsfiddle切換d3.js餅圖應用程序作爲我的最新版本http://jsfiddle.net/Qh9X5/3328/d3.js dougnut餅圖圖例切換

我的目標是獲得一個簡化的工作示例,其中圖例可以切換切片,試圖停用所有切片 - 在重新激活所有切片的重置中切除。分解演示文稿和應用程序層邏輯。

補間也需要改進 - 隨着切片流入存在,然後順利地重新補間。

如何改善/修復此代碼庫中的各種錯誤?

onLegendClick: function(dt, i){ 
        //_toggle rectangle in legend 

var completeData = jQuery.extend(true, [], methods.currentDataSet); 




        newDataSet = completeData;       
        if(methods.manipulatedData){ 
         newDataSet = methods.manipulatedData; 
        } 


        d3.selectAll('rect') 
        .data([dt], function(d) { 
         return d.data.label; 
        }) 
        .style("fill-opacity", function(d, j) { 
         var isActive = Math.abs(1-d3.select(this).style("fill-opacity")); 
         if(isActive){ 
          newDataSet[j].total = completeData[j].total;         
         }else{ 
          newDataSet[j].total = 0;        
         } 

         return isActive; 
        });        

        //animate slices 
        methods.animateSlices(newDataSet); 

        //stash manipulated data 
        methods.manipulatedData = newDataSet; 

       } 
+0

是否有隱藏在這裏的問題? :o – 2014-10-27 12:18:46

+0

如何修復/改進代碼庫? – 2014-10-27 12:20:56

+1

http://codereview.stackexchange.com/似乎更適合要求對您的代碼進行改進/審覈。 – 2014-10-27 12:26:15

回答

0

這是整個js代碼 - 我已經使用了tidyup。我不確定使用快捷鍵,因爲我不確定這些值是否正確。最新的小提琴 - http://jsfiddle.net/Qh9X5/3340/

$(document).ready(function() { 

    var pieChart = { 
     el: "", 
     init: function (el, options) { 
      var clone = jQuery.extend(true, {}, options["data"]); 

      pieChart.el = el; 
      pieChart.setup(clone, options["width"], options["height"], options["r"], options["ir"]); 
     }, 
     getArc: function (radius, innerradius) { 
      var arc = d3.svg.arc() 
       .innerRadius(innerradius) 
       .outerRadius(radius); 

      return arc; 
     }, 
     setup: function (dataset, w, h, r, ir) { 

      var padding = 80; 

      this.width = w; 
      this.height = h; 
      this.radius = r 
      this.innerradius = ir; 

      this.color = d3.scale.category20(); 

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

      this.arc = this.getArc(this.radius, this.innerradius); 

      this.svg = d3.select(pieChart.el["selector"]).append("svg") 
       .attr("width", this.width + padding) 
       .attr("height", this.height + padding); 

      this.holder = this.svg.append("g") 
       .attr("transform", "translate(" + ((this.width/2) + (padding/2)) + "," + ((this.height/2) + (padding/2)) + ")"); 

      this.piec = this.holder.append("g") 
       .attr("class", "piechart"); 

      this.segments = this.holder.append("g") 
       .attr("class", "segments"); 

      this.labels = this.holder.append("g") 
       .attr("class", "labels"); 

      this.pointers = this.holder.append("g") 
       .attr("class", "pointers"); 

      this.legend = this.svg.append("g") 
       .attr("class", "legend") 
       .attr("transform", "translate(" + -(this.width/4) + "," + this.height + ")"); 

     }, 
     oldPieData: "", 
     pieTween: function (r, ir, d, i) { 
      var that = this; 

      var theOldDataInPie = pieChart.oldPieData; 
      // Interpolate the arcs in data space 

      var s0; 
      var e0; 

      if (theOldDataInPie[i]) { 
       s0 = theOldDataInPie[i].startAngle; 
       e0 = theOldDataInPie[i].endAngle; 
      } else if (!(theOldDataInPie[i]) && theOldDataInPie[i - 1]) { 
       s0 = theOldDataInPie[i - 1].endAngle; 
       e0 = theOldDataInPie[i - 1].endAngle; 
      } else if (!(theOldDataInPie[i - 1]) && theOldDataInPie.length > 0) { 
       s0 = theOldDataInPie[theOldDataInPie.length - 1].endAngle; 
       e0 = theOldDataInPie[theOldDataInPie.length - 1].endAngle; 
      } else { 
       s0 = 0; 
       e0 = 0; 
      } 

      var i = d3.interpolate({ 
       startAngle: s0, 
       endAngle: e0 
      }, { 
       startAngle: d.startAngle, 
       endAngle: d.endAngle 
      }); 

      return function (t) { 
       var b = i(t); 
       return pieChart.getArc(r, ir)(b); 
      }; 
     }, 
     removePieTween: function (r, ir, d, i) { 
      var that = this; 
      s0 = 2 * Math.PI; 
      e0 = 2 * Math.PI; 
      var i = d3.interpolate({ 
       startAngle: d.startAngle, 
       endAngle: d.endAngle 
      }, { 
       startAngle: s0, 
       endAngle: e0 
      }); 

      return function (t) { 
       var b = i(t); 
       return pieChart.getArc(r, ir)(b); 
      }; 
     }, 
     animateSlices: function (dataSet) { 

      var r = $(pieChart.el["selector"]).data("r"); 
      var ir = $(pieChart.el["selector"]).data("ir"); 

      this.piedata = pieChart.pie(dataSet); 

      //__slices 
      this.path = pieChart.segments.selectAll("path.pie") 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      this.path.enter().append("path") 
       .attr("class", "pie") 
       .attr("fill", function (d, i) { 
       return pieChart.color(i); 
      }) 
       .attr("stroke", "#ffffff") 
       .transition() 
       .duration(300) 
       .attrTween("d", function (d, i) { 
       return pieChart.pieTween(r, ir, d, i); 
      }); 

      this.path.transition() 
       .duration(300) 
       .attrTween("d", function (d, i) { 
       return pieChart.pieTween(r, ir, d, i); 
      }); 

      this.path.exit() 
       .transition() 
       .duration(300) 
       .attrTween("d", function (d, i) { 
       return pieChart.removePieTween(r, ir, d, i); 
      }) 
       .remove(); 
      //__slices 

      //__labels 
      var labels = pieChart.labels.selectAll("text") 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      labels.enter() 
       .append("text") 
       .attr("text-anchor", "middle") 

      labels.attr("x", function (d) { 
       var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2; 
       d.cx = Math.cos(a) * (ir + ((r - ir)/2)); 
       return d.x = Math.cos(a) * (r + 20); 
      }) 
       .attr("y", function (d) { 
       var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2; 
       d.cy = Math.sin(a) * (ir + ((r - ir)/2)); 
       return d.y = Math.sin(a) * (r + 20); 
      }) 
       .attr("opacity", function (d) { 
       var opacityLevel = 1; 
       if (d.value == 0) { 
        opacityLevel = 0; 
       } 
       return opacityLevel; 
      }) 
       .text(function (d) { 
       return d.data.label; 
      }) 
       .each(function (d) { 
       var bbox = this.getBBox(); 
       d.sx = d.x - bbox.width/2 - 2; 
       d.ox = d.x + bbox.width/2 + 2; 
       d.sy = d.oy = d.y + 5; 
      }) 
       .transition() 
       .duration(300) 

      labels.transition() 
       .duration(300) 

      labels.exit().remove(); 
      //__labels 

      //__pointers 
      pieChart.pointers.append("defs").append("marker") 
       .attr("id", "circ") 
       .attr("markerWidth", 6) 
       .attr("markerHeight", 6) 
       .attr("refX", 3) 
       .attr("refY", 3) 
       .append("circle") 
       .attr("cx", 3) 
       .attr("cy", 3) 
       .attr("r", 3); 

      var pointers = pieChart.pointers.selectAll("path.pointer") 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      pointers.enter() 
       .append("path") 
       .attr("class", "pointer") 
       .style("fill", "none") 
       .style("stroke", "black") 
       .attr("marker-end", "url(#circ)"); 

      pointers.attr("d", function (d) { 
       if (d.cx > d.ox) { 
        return "M" + d.sx + "," + d.sy + "L" + d.ox + "," + d.oy + " " + d.cx + "," + d.cy; 
       } else { 
        return "M" + d.ox + "," + d.oy + "L" + d.sx + "," + d.sy + " " + d.cx + "," + d.cy; 
       } 
      }) 
       .attr("opacity", function (d) { 
       var opacityLevel = 1; 
       if (d.value == 0) { 
        opacityLevel = 0; 
       } 
       return opacityLevel; 
      }) 
       .transition() 
       .duration(300) 

      pointers.transition() 
       .duration(300) 

      pointers.exit().remove(); 
     }, 
     onToggle: function (sliceData, index) { 
      //_toggle rectangle in legend 

      //_toggle slice 
      var completeData = jQuery.extend(true, [], pieChart.currentDataSet); 
      var dataLength = completeData.length; 

      var newDataSet = completeData; 
      if (pieChart.manipulatedData) { 
       newDataSet = pieChart.manipulatedData; 
      } 

      d3.selectAll('rect') 
       .data([sliceData], function (d) { 
       return d.data.label; 
      }) 
       .style("fill-opacity", function (d) { 
       var isActive = Math.abs(1 - d3.select(this).style("fill-opacity")); 
       if (isActive) { 
        newDataSet[index].total = completeData[index].total; 
        newDataSet[index].value = completeData[index].value; 
       } else { 
        newDataSet[index].total = 0; 
        newDataSet[index].value = 0; 
       } 

       return isActive; 
      }); 

      //if all elements are to be not shown - reset to show all slices again. 
      //animate slices 
      pieChart.animateSlices(newDataSet); 

      //stash manipulated data 
      pieChart.manipulatedData = newDataSet; 
     }, 
     update: function (el, dataSet) { 
      var that = this; 

      pieChart.el = el; 

      pieChart.svg = d3.select(pieChart.el["selector"] + " .piechart"); 

      pieChart.segments = d3.select(pieChart.el["selector"] + " .segments"); 
      pieChart.labels = d3.select(pieChart.el["selector"] + " .labels"); 
      pieChart.pointers = d3.select(pieChart.el["selector"] + " .pointers"); 

      pieChart.legend = d3.select(pieChart.el["selector"] + " .legend"); 

      dataSet.forEach(function (d) { 
       d.total = +d.value; 
      }); 

      pieChart.currentDataSet = dataSet; 
      pieChart.animateSlices(dataSet); 

      //__legends 
      var w = 200; 

      // add legend 
      var legend = pieChart.legend; //.append("g") 

      var legendRects = legend.selectAll('rect') 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      legendRects.enter() 
       .append("rect") 
       .attr("x", w - 65) 
       .attr("y", function (d, i) { 
       return i * 20; 
      }) 
       .attr("width", 10) 
       .attr("height", 10) 
       .style("fill", function (d, i) { 
       return pieChart.color(i); 
      }) 
       .style("stroke", function (d, i) { 
       return pieChart.color(i); 
      }) 
      .on('click', function(d, i){ 
       pieChart.onToggle(d, i); 
      }) 
       .transition() 
       .duration(300) 

      legendRects.style("fill", function (d, i) { 
       return pieChart.color(i); 
      }) 
       .style("stroke", function (d, i) { 
       return pieChart.color(i); 
      }) 
       .transition() 
       .duration(300) 

      legendRects.exit().remove(); 

      var legendText = legend.selectAll('text.label') 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      legendText.enter() 
       .append("text") 
       .attr("class", "label") 
       .attr("x", w - 52) 
       .attr("y", function (d, i) { 
       return i * 20 + 9; 
      }) 
       .text(function (d) { 
       return d.data.label; 
      }) 
       .transition() 
       .duration(300) 

      legendText.text(function (d) { 
       return d.data.label; 
      }) 
       .transition() 
       .duration(300) 

      legendText.exit().remove(); 

      var legendTextVals = legend.selectAll('text.vals') 
       .data(this.piedata, function (d) { 
       return d.data.label 
      }); 

      legendTextVals.enter() 
       .append("text") 
       .attr("class", "vals") 
       .attr("x", w + 20) 
       .attr("y", function (d, i) { 
       return i * 20 + 9; 
      }) 
       .text(function (d) { 
       return d.data.value; 
      }) 
       .transition() 
       .duration(300) 

      legendTextVals.text(function (d) { 
       return d.data.value; 
      }) 
       .transition() 
       .duration(300) 

      legendTextVals.exit().remove(); 

      //__pointers 

      this.oldPieData = this.piedata; 
     } 
    }; 

    var dataCharts = [{ 
     "data": [{ 
      "segments": [{ 
       "label": "apple", 
        "value": 53245 
      }, { 
       "label": "cherry", 
        "value": 145 
      }, { 
       "label": "pear", 
        "value": 2245 
      }, { 
       "label": "bananana", 
        "value": 15325 
      }] 
     }] 
    }, { 
     "data": [{ 
      "segments": [{ 
       "label": "milk", 
        "value": 122 
      }, { 
       "label": "cheese", 
        "value": 44 
      }, { 
       "label": "grapes", 
        "value": 533 
      }] 
     }] 
    }, { 
     "data": [{ 
      "segments": [{ 
       "label": "pineapple", 
        "value": 1532 
      }, { 
       "label": "orange", 
        "value": 1435 
      }, { 
       "label": "grapes", 
        "value": 22 
      }] 
     }] 
    }, { 
     "data": [{ 
      "segments": [{ 
       "label": "lemons", 
        "value": 133 
      }, { 
       "label": "mango", 
        "value": 435 
      }, { 
       "label": "melon", 
        "value": 2122 
      }] 
     }] 
    }]; 

    var clone = jQuery.extend(true, {}, dataCharts); 

    //__invoke concentric 
    $('[data-role="piechart"]').each(function (index) { 
     var selector = "piechart" + index; 

     $(this).attr("id", selector); 

     var options = { 
      data: clone[0].data, 
      width: $(this).data("width"), 
      height: $(this).data("height"), 
      r: $(this).data("r"), 
      ir: $(this).data("ir") 
     } 

     pieChart.init($("#" + selector), options); 
     pieChart.update($("#" + selector), clone[0].data[0].segments); 
    }); 

    $(".testers a").on("click", function (e) { 
     e.preventDefault(); 

     var clone = jQuery.extend(true, {}, dataCharts); 

     var min = 0; 
     var max = 3; 

     //__invoke pie chart 
     $('[data-role="piechart"]').each(function (index) { 
      pos = Math.floor(Math.random() * (max - min + 1)) + min; 
      pieChart.update($("#" + $(this).attr("id")), clone[pos].data[0].segments); 
     }); 
    }); 
});