Amcharts 桑基图:如何在悬停链接时查看所有“后续”路径

问题描述 投票:0回答:1

我对使用 AmCharts 制作“可追踪桑基图”非常感兴趣,就像在这里可以体验到的那样: https://www.amcharts.com/demos/traceable-sankey-diagram/

当您将鼠标移到链接(例如 C-F)上时,您可以看到其他突出显示的链接(即 F-I + I-Q)。 这是一个很棒的功能,但我希望它略有不同。我希望所有“兼容”链接都突出显示(F-I,还有 F-M。然后是 I-Q、I-R、I-S、I-T 和 M-U),因为所有这些都可以遵循 C-F。

可行吗?我在 Amchart 的文档中找不到任何选项。 谢谢,

amcharts sankey-diagram
1个回答
0
投票

需要一种新的算法来选择突出显示的项目。要选择所有兼容的目标及其目标,...等等,可以:

  1. 以指针下的项目开始数组
    itemsToHighlight
    ,并在数组
    allTargetIds
    中最初存储该项目的目标ID
  2. 对于该系列的所有链接,将其
    源 id
    等于 itemsToHighlight 数组中的目标 id 之一的所有项目添加到
    allTargetIds
  3. 重复步骤2。直到没有新项目添加到
    itemsToHighlight

现在,如果还想在左侧突出显示兼容的项目,即所有可能的源及其所有可能的源,...等等,算法是相同的,但反转源和目标位置。

这是代码中的那部分:

var itemsToHighlight = [];
series.links.template.events.on("pointerover", function(event) {
    var dataItem = event.target.dataItem;
    itemsToHighlight = [dataItem];
    var allTargetIds = [dataItem.get("targetId")];
    var allSourceIds = [dataItem.get("sourceId")];

    // all compatible (possible) targets, and their possible
    // targets, and so on until nothing new is found 
    var newItems = true;
    while (newItems) {
        newItems = false;
        am5.array.each(series.dataItems, function(dataItem) {
            if (itemsToHighlight.indexOf(dataItem) < 0 &&
                    allTargetIds.indexOf(dataItem.get("sourceId")) >= 0) {
                allTargetIds.push(dataItem.get("targetId"));
                itemsToHighlight.push(dataItem);
                newItems = true;
            }
        });
    }

    // all compatible (possible) sources, and their possible
    // sources, and so on until nothing new is found 
    newItems = true;
    while (newItems) {
        newItems = false;
        am5.array.each(series.dataItems, function(dataItem) {
            if (itemsToHighlight.indexOf(dataItem) < 0 &&
                    allSourceIds.indexOf(dataItem.get("targetId")) >= 0) {
                allSourceIds.push(dataItem.get("sourceId"));
                itemsToHighlight.push(dataItem);
                newItems = true;
           }
        });
    }
  
    am5.array.each(itemsToHighlight, function(dataItem) {
        dataItem.get("link").hover();
    });
});

series.links.template.events.on("pointerout", function(event) {    
    am5.array.each(itemsToHighlight, function(dataItem) {
        dataItem.get("link").unhover();
    });
    itemsToHighlight = [];
});

这仅针对链接实现,如我们开始的示例所示。节点保持其默认行为以仅突出显示其直接源和目标。然而,类似于链接的行为也可以扩展到节点,只需进行最小的调整。

改编后的示例摘录:

/**
 * ---------------------------------------
 * This demo was created using amCharts 5.
 * 
 * For more information visit:
 * https://www.amcharts.com/
 * 
 * Documentation is available at:
 * https://www.amcharts.com/docs/v5/
 * ---------------------------------------
 */

// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");

// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([am5themes_Animated.new(root)]);

// Create series
// https://www.amcharts.com/docs/v5/charts/flow-charts/
var series = root.container.children.push(
  am5flow.Sankey.new(root, {
    sourceIdField: "from",
    targetIdField: "to",
    valueField: "value",
    paddingRight: 50,
    idField: "id"
  })
);

series.links.template.setAll({
  fillStyle: "solid",
  fillOpacity: 0.15
});


var itemsToHighlight = [];
series.links.template.events.on("pointerover", function(event) {
  var dataItem = event.target.dataItem;
  itemsToHighlight = [dataItem];
  var allTargetIds = [dataItem.get("targetId")];
  var allSourceIds = [dataItem.get("sourceId")];

  // all compatible (possible) targets, and their possible 
  // targets, and so on until nothing new is found 
  var newItems = true;
  while (newItems) {
    newItems = false;
    am5.array.each(series.dataItems, function(dataItem) {
      if (itemsToHighlight.indexOf(dataItem) < 0 &&
        allTargetIds.indexOf(dataItem.get("sourceId")) >= 0) {
        allTargetIds.push(dataItem.get("targetId"));
        itemsToHighlight.push(dataItem);
        newItems = true;
      }
    });
  }

  // all compatible (possible) sources, and their possible 
  // sources, and so on until nothing new is found 
  newItems = true;
  while (newItems) {
    newItems = false;
    am5.array.each(series.dataItems, function(dataItem) {
      if (itemsToHighlight.indexOf(dataItem) < 0 &&
        allSourceIds.indexOf(dataItem.get("targetId")) >= 0) {
        allSourceIds.push(dataItem.get("sourceId"));
        itemsToHighlight.push(dataItem);
        newItems = true;
      }
    });
  }
  
  am5.array.each(itemsToHighlight, function(dataItem) {
    dataItem.get("link").hover();
  });
});

series.links.template.events.on("pointerout", function(event) {
  am5.array.each(itemsToHighlight, function(dataItem) {
    dataItem.get("link").unhover();
  });
  itemsToHighlight = [];
});

// Set data
// https://www.amcharts.com/docs/v5/charts/flow-charts/#Setting_data
series.data.setAll([{
    from: "A",
    to: "E",
    value: 1,
    id: "A0-0"
  },
  {
    from: "A",
    to: "F",
    value: 1,
    id: "A1-0"
  },
  {
    from: "A",
    to: "G",
    value: 1,
    id: "A2-0"
  },

  {
    from: "B",
    to: "E",
    value: 1,
    id: "B0-0"
  },
  {
    from: "B",
    to: "F",
    value: 1,
    id: "B1-0"
  },
  {
    from: "B",
    to: "G",
    value: 1,
    id: "B2-0"
  },

  {
    from: "C",
    to: "F",
    value: 1,
    id: "C0-0"
  },
  {
    from: "C",
    to: "G",
    value: 1,
    id: "C1-0"
  },
  {
    from: "C",
    to: "H",
    value: 1,
    id: "C2-0"
  },

  {
    from: "D",
    to: "E",
    value: 1,
    id: "D0-0"
  },
  {
    from: "D",
    to: "F",
    value: 1,
    id: "D1-0"
  },
  {
    from: "D",
    to: "G",
    value: 1,
    id: "D2-0"
  },
  {
    from: "D",
    to: "H",
    value: 1,
    id: "D3-0"
  },

  {
    from: "E",
    to: "I",
    value: 1,
    id: "A0-1"
  },
  {
    from: "E",
    to: "I",
    value: 1,
    id: "B0-1"
  },
  {
    from: "E",
    to: "L",
    value: 1,
    id: "D0-1"
  },

  {
    from: "F",
    to: "I",
    value: 1,
    id: "A1-1"
  },
  {
    from: "F",
    to: "I",
    value: 1,
    id: "C0-1"
  },
  {
    from: "F",
    to: "I",
    value: 1,
    id: "D1-1"
  },
  {
    from: "F",
    to: "M",
    value: 1,
    id: "B1-1"
  },

  {
    from: "G",
    to: "I",
    value: 1,
    id: "A2-1"
  },
  {
    from: "G",
    to: "I",
    value: 1,
    id: "B2-1"
  },
  {
    from: "G",
    to: "J",
    value: 1,
    id: "C1-1"
  },
  {
    from: "G",
    to: "N",
    value: 1,
    id: "D2-1"
  },

  {
    from: "H",
    to: "K",
    value: 1,
    id: "C2-1"
  },
  {
    from: "H",
    to: "N",
    value: 1,
    id: "D3-1"
  },

  {
    from: "I",
    to: "O",
    value: 1,
    id: "A0-2"
  },
  {
    from: "I",
    to: "O",
    value: 1,
    id: "B2-2"
  },
  {
    from: "I",
    to: "Q",
    value: 1,
    id: "A1-2"
  },
  {
    from: "I",
    to: "R",
    value: 1,
    id: "A2-2"
  },
  {
    from: "I",
    to: "S",
    value: 1,
    id: "D1-2"
  },
  {
    from: "I",
    to: "T",
    value: 1,
    id: "B0-2"
  },
  {
    from: "I",
    to: "Q",
    value: 1,
    id: "C0-2"
  },

  {
    from: "J",
    to: "U",
    value: 1,
    id: "C1-2"
  },

  {
    from: "K",
    to: "V",
    value: 1,
    id: "C2-2"
  },
  {
    from: "M",
    to: "U",
    value: 1,
    id: "B1-2"
  },

  {
    from: "N",
    to: "Q",
    value: 1,
    id: "D2-2"
  },
  {
    from: "N",
    to: "Q",
    value: 1,
    id: "D3-2"
  },

  {
    from: "L",
    to: "W",
    value: 1,
    id: "D0-2"
  }
]);

// Make stuff animate on load
series.appear(1000, 100);
body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
}

#chartdiv {
  width: 100%;
  height: 500px;
}
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/flow.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
<div id="chartdiv"></div>

或在jsFiddle中。

© www.soinside.com 2019 - 2024. All rights reserved.