在具有交互性的酒窝多系列图表中更新系列订单

时间:2016-01-28 21:59:09

标签: javascript jquery d3.js charts dimple.js

我已经创建了一个酒窝交互式图表的版本(请参阅dimplejs.org/advanced_examples_viewer.html?id=advanced_interactive_legends)  有两个系列:一个饼图系列和一个基于相同数据集的系列。

jsfiddle:http://jsfiddle.net/jose_jimenez/1fvjvyvh/3/

 var svg = dimple.newSvg("#chartContainer", 700, 500);
 var mainSlicer = "classification";
 var pies;
 var lines;

//data here look for ------END OF DATA --------
 var data = [{
   "classification": "Undergraduate",
   "residency": "Resident",
   "year": 2006,
   "head count": 14011
 }, {
   "classification": "Undergraduate",
   "residency": "Domestic",
   "year": 2006,
   "head count": 6347
 }, {
   "classification": "Undergraduate",
   "residency": "International",
   "year": 2006,
   "head count": 380
 }, {
   "classification": "Graduate",
   "residency": "Resident",
   "year": 2006,
   "head count": 2693
 }, {
   "classification": "Graduate",
   "residency": "Domestic",
   "year": 2006,
   "head count": 2075
 }, {
   "classification": "Graduate",
   "residency": "International",
   "year": 2006,
   "head count": 1309
 }, {
   "classification": "Professional",
   "residency": "Resident",
   "year": 2006,
   "head count": 1374
 }, {
   "classification": "Professional",
   "residency": "Domestic",
   "year": 2006,
   "head count": 612
 }, {
   "classification": "Professional",
   "residency": "International",
   "year": 2006,
   "head count": 14
 }, {
   "classification": "Postgraduate",
   "residency": "Resident",
   "year": 2006,
   "head count": 825
 }, {
   "classification": "Postgraduate",
   "residency": "Domestic",
   "year": 2006,
   "head count": 38
 }, {
   "classification": "Postgraduate",
   "residency": "International",
   "year": 2006,
   "head count": 301
 }, {
   "classification": "Undergraduate",
   "residency": "Resident",
   "year": 2007,
   "head count": 13808
 }, {
   "classification": "Undergraduate",
   "residency": "Domestic",
   "year": 2007,
   "head count": 6695
 }, {
   "classification": "Undergraduate",
   "residency": "International",
   "year": 2007,
   "head count": 404
 }, {
   "classification": "Graduate",
   "residency": "Resident",
   "year": 2007,
   "head count": 2848
 }, {
   "classification": "Graduate",
   "residency": "Domestic",
   "year": 2007,
   "head count": 2127
 }, {
   "classification": "Graduate",
   "residency": "International",
   "year": 2007,
   "head count": 1246
 }, {
   "classification": "Professional",
   "residency": "Resident",
   "year": 2007,
   "head count": 1338
 }, {
   "classification": "Professional",
   "residency": "Domestic",
   "year": 2007,
   "head count": 642
 }, {
   "classification": "Professional",
   "residency": "International",
   "year": 2007,
   "head count": 16
 }, {
   "classification": "Postgraduate",
   "residency": "Resident",
   "year": 2007,
   "head count": 930
 }, {
   "classification": "Postgraduate",
   "residency": "Domestic",
   "year": 2007,
   "head count": 53
 }, {
   "classification": "Postgraduate",
   "residency": "International",
   "year": 2007,
   "head count": 302
 }, {
   "classification": "Undergraduate",
   "residency": "Resident",
   "year": 2008,
   "head count": 13192
 }, {
   "classification": "Undergraduate",
   "residency": "Domestic",
   "year": 2008,
   "head count": 7055
 }, {
   "classification": "Undergraduate",
   "residency": "International",
   "year": 2008,
   "head count": 576
 }, {
   "classification": "Graduate",
   "residency": "Resident",
   "year": 2008,
   "head count": 2932
 }, {
   "classification": "Graduate",
   "residency": "Domestic",
   "year": 2008,
   "head count": 2164
 }, {
   "classification": "Graduate",
   "residency": "International",
   "year": 2008,
   "head count": 1247
 }, {
   "classification": "Professional",
   "residency": "Resident",
   "year": 2008,
   "head count": 1288
 }, {
   "classification": "Professional",
   "residency": "Domestic",
   "year": 2008,
   "head count": 687
 }, {
   "classification": "Professional",
   "residency": "International",
   "year": 2008,
   "head count": 22
 }, {
   "classification": "Postgraduate",
   "residency": "Resident",
   "year": 2008,
   "head count": 994
 }, {
   "classification": "Postgraduate",
   "residency": "Domestic",
   "year": 2008,
   "head count": 58
 }, {
   "classification": "Postgraduate",
   "residency": "International",
   "year": 2008,
   "head count": 346
 }];
 // ------END OF DATA --------

 function addSeries(chart) {
   pies = chart.addSeries(slicer, dimple.plot.pie);
   lines = chart.addSeries("classification", dimple.plot.line);
   lines.lineMarkers = true;
   lines.lineWeight = 5;
   pies.radius = 20;
 }

 function createChart() {

   data_attributes = Object.getOwnPropertyNames(data[0]);
   ['year', 'head count', mainSlicer].forEach(function(f) {
     data_attributes.splice(data_attributes.indexOf(f), 1);
   });
   slicer = data_attributes[0];
   var myChart = new dimple.chart(svg, data);
   myChart.setBounds(60, 30, 500, 400)
   var x = myChart.addCategoryAxis("x", ["year", mainSlicer]);
   x.addOrderRule("year");
   myChart.addMeasureAxis("y", "head count");
   myChart.addMeasureAxis("p", "head count");
   addSeries(myChart);
   var myClassificationLegend = myChart.addLegend(550, 200, 150, 400, "left", lines);
   var mySlicerLegend = myChart.addLegend(550, 300, 150, 400, "left", pies);

   myChart.draw();

   myChart.legends = [];

   svg.selectAll("title_text")
     .data(["Click legend to", "show/hide segments:"])
     .enter()
     .append("text")
     .attr("x", 550)
     .attr("y", function(d, i) {
       return 160 + i * 14;
     })
     .style("font-family", "sans-serif")
     .style("font-size", "10px")
     .style('font-weight', 'bold')
     .style("color", "Black")
     .text(function(d) {
       return d;
     });


   var classFilterValues = dimple.getUniqueValues(data, mainSlicer);
   var slicerFilterValues = dimple.getUniqueValues(data, slicer);
   var hiddenValues = [];

   legendBits = myClassificationLegend.shapes;
   legendBits[0] = legendBits[0]
     .concat(mySlicerLegend.shapes[0]);

   legendBits.selectAll('rect')
     // Add a click event to each rectangle
     .on("click", function(e) {
       // This indicates whether the item is already visible or not
       var hide = false;
       var newClassificationFilters = [];
       var newSlicerFilters = [];
       var currentValue = e.aggField.slice(-1)[0];

       // If the filters contain the clicked shape hide it
       var whereIsIt = hiddenValues.indexOf(currentValue);
       if (whereIsIt > -1) {
         //it is hidden and needs to be shown.
         hide = false;
         hiddenValues.splice(whereIsIt, 1);
       } else {
         //it needs to be hidden
         hide = true;
         hiddenValues.push(currentValue);
       }


       classFilterValues.forEach(function(f) {
         if (hiddenValues.indexOf(f) < 0) {
           newClassificationFilters.push(f);
         }
       });
       slicerFilterValues.forEach(function(f) {
         if (hiddenValues.indexOf(f) < 0) {
           newSlicerFilters.push(f);
         }
       });
       // Hide the shape or show it
       if (hide) {
         d3.select(this).style("opacity", 0.2);
       } else {
         d3.select(this).style("opacity", 0.8);
       }

       // Filter the data
       myChart.data = dimple.filterData(dimple.filterData(data, 'classification', newClassificationFilters), slicer, newSlicerFilters);
       // Passing a duration parameter makes the chart animate. Without
       // it there is no transition

       myChart.draw(800, false);

     });

 }

 function moveLegend(legend, offset) {
   $(legend).find('text,rect').attr('y', parseInt($(f).find('text').attr('y')) + offset);
 }

 createChart();

我在馅饼之后渲染了系列线,因此线条最终位于馅饼段的顶部。这允许访问线序列的鼠标悬停交互性。

当馅饼段关闭然后再打开时,它们会在回来时最终呈现在线段的顶部。这可能是因为路径被添加到图表对象的末尾而不是在行系列之前插入。最终他们阻止了系列交互。

我尝试了几种解决方案,包括:

  • 尝试使用the将pie.shapes.selectAll('path')移回 d3.prototype.moveToBack代码(参见bl.ocks.org/eesur/4e0a69d57d3bfc8a82c2)
    • 路径没有parentNodes,或者parentNodes没有childNodes
  • 尝试删除系列并使用chart.series.slice将其重新添加回来,或者只使用chart.series = []删除它们
    • 之后图表一团糟,因为没有删除所有对象。
    • 删除pie.shapes和/或line.shapes没有多大帮助。

我可以通过隐藏所有线条并将它们带回来来将它们带回来(添加的顺序使得线条返回顶部)。

我想跳进路径并使用jquery删除它们并将它们添加回来,这将感觉像一个完全黑客。任何人都有更优雅的方式处理这个?

2 个答案:

答案 0 :(得分:1)

您需要在chart.addSeries中执行的操作是将每个系列添加到单独的&#39; g&#39; svg中的元素。目前,您的圆圈和线条都在同一个g元素中混合,因此最后添加的元素始终位于顶部。

e.g。 所以

<g>
<path>
<circle>
<path>
<newly appended circle>
</g>

变为

<g>
<circle>
<newly appended circle>
</g>
<g>
<path>
<path>
</g> 

所有路径将始终在所有圆圈之后绘制,因为svg只是按上面的顺序绘制元素

答案 1 :(得分:0)

因此,事实证明,dimple 2.1.6将任意数量的系列的所有系列元素添加到与@mgraham指出的相同<g>元素中。相信这一点。 AlignAnalytics dimple repo上的问题#203向其他人展示了同样的问题。我把它分叉并为每个系列添加了组。请参阅同一仓库中的拉出请求#207。希望他们能把它拉进来。

https://github.com/PMSI-AlignAlytics/dimple/pull/207