更新具有交互性的酒窝多系列图表中的系列顺序

update series order in dimple multi-series chart with interactivity

我创建了一个版本的 dimple 交互式图表(参见 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();

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

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

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

我可以通过隐藏所有行并将它们带回来(添加顺序使行回到顶部)。

我想跳入路径并使用 jquery 删除它们并重新添加它们,这感觉就像一个完全的 hack。谁有更优雅的方法来处理这个问题?

您需要在 chart.addSeries 中做的是将每个系列添加到 svg 中单独的 'g' 元素。目前,您的圆圈和线条都混合在同一个 g 元素中,因此最后添加的元素始终绘制在顶部。

例如 所以

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

变成

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

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

所以,事实证明,dimple 2.1.6 将任意数量系列的所有系列元素添加到相同的 <g> 元素,如@mgraham 指出的那样。值得称赞的是。 AlignAnalytics dimple repo 上的 Issue #203 显示其他人也有同样的问题。我分叉它并为每个系列添加了组。请参阅同一回购协议中的拉取请求#207。希望他们能把它拉进来。

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