Stacked Area Amchart 传递动态数据

Stacked Area Amchart passing dynamic data

**参考 - https://www.amcharts.com/demos/stacked-area/ 它只在 y 轴上绘制一个用户,而我希望所有用户数据都在堆积线区域中。

我想我需要在数据系列上创建一个函数,但真的不知道该怎么做。 我希望 X 轴是 Date ,Y 轴是显示多行用户 [A,B,C,D] **

的值标度

< script >
  var df = [{
    "User": "A",
    "Date": 1570492800000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570492800000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570492800000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570492800000,
    "value_act": 0.0
  }, {
    "User": "A",
    "Date": 1570579200000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570579200000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570579200000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570579200000,
    "value_act": 0.0
  }, {
    "User": "A",
    "Date": 1570838400000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570838400000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570838400000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570838400000,
    "value_act": 0.0
  }]


console.log(df);

am4core.ready(function() {

  // Themes begin
  am4core.useTheme(am4themes_animated);
  // Themes end

  var chart = am4core.create("lines1", am4charts.XYChart);

  chart.data = df;

  chart.dateFormatter.inputDateFormat = "yyyy";
  var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
  dateAxis.renderer.minGridDistance = 60;
  dateAxis.startLocation = 0.5;
  dateAxis.endLocation = 0.5;
  dateAxis.baseInterval = {
    timeUnit: "Date",
    count: 1
  }

  var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  valueAxis.tooltip.disabled = true;


  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "User";
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;

  chart.cursor = new am4charts.XYCursor();
  chart.cursor.xAxis = dateAxis;
  chart.scrollbarX = new am4core.Scrollbar();

  // Add a legend
  chart.legend = new am4charts.Legend();
  chart.legend.position = "top";

});
// end am4core.ready()
<
/script>
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="lines1"></div>

要有多条线,需要向图表添加多个系列

每个系列都需要数据中的特定键

所以,不是所有人都有 "User"
的密钥 我们需要 4 个单独的键 --> "UserA", "UserB", "UserC", "UserD"

var df = [{
  "UserA": "A",
  "Date": 1570492800000,
  "value_act": 3.4
}, {
  "UserB": "B",
  "Date": 1570492800000,
  "value_act": 1.6
}, {
  "UserC": "C",
  "Date": 1570492800000,
  "value_act": 4.7
}, {
  "UserD": "D",
  "Date": 1570492800000,
  "value_act": 0.0
}, {

请参阅以下工作片段...

am4core.ready(function() {

// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end

  var df = [{
    "UserA": "A",
    "Date": 1570492800000,
    "value_act": 3.4
  }, {
    "UserB": "B",
    "Date": 1570492800000,
    "value_act": 1.6
  }, {
    "UserC": "C",
    "Date": 1570492800000,
    "value_act": 4.7
  }, {
    "UserD": "D",
    "Date": 1570492800000,
    "value_act": 0.0
  }, {
    "UserA": "A",
    "Date": 1570579200000,
    "value_act": 3.4
  }, {
    "UserB": "B",
    "Date": 1570579200000,
    "value_act": 1.6
  }, {
    "UserC": "C",
    "Date": 1570579200000,
    "value_act": 4.7
  }, {
    "UserD": "D",
    "Date": 1570579200000,
    "value_act": 0.0
  }, {
    "UserA": "A",
    "Date": 1570838400000,
    "value_act": 3.4
  }, {
    "UserB": "B",
    "Date": 1570838400000,
    "value_act": 1.6
  }, {
    "UserC": "C",
    "Date": 1570838400000,
    "value_act": 4.7
  }, {
    "UserD": "D",
    "Date": 1570838400000,
    "value_act": 0.0
  }]

am4core.ready(function() {

  // Themes begin
  am4core.useTheme(am4themes_animated);
  // Themes end

  var chart = am4core.create("lines1", am4charts.XYChart);

  chart.data = df;

  chart.dateFormatter.inputDateFormat = "yyyy";
  var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
  dateAxis.renderer.minGridDistance = 60;
  dateAxis.startLocation = 0.5;
  dateAxis.endLocation = 0.5;
  dateAxis.baseInterval = {
    timeUnit: "Date",
    count: 1
  }

  var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  valueAxis.tooltip.disabled = true;


  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "UserA";
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;

  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "UserB";
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;

  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "UserC";
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;

  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "UserD";
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;

  chart.cursor = new am4charts.XYCursor();
  chart.cursor.xAxis = dateAxis;
  chart.scrollbarX = new am4core.Scrollbar();

  // Add a legend
  chart.legend = new am4charts.Legend();
  chart.legend.position = "top";

});

});
#lines1 {
  width: 100%;
  height: 500px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="lines1"></div>


编辑

动态构建单独的系列,
让我们首先恢复到原始数据集,
其中每一行都有相同的 "User" 键和不同的值。

var df = [{
  "User": "A",
  "Date": 1570492800000,
  "value_act": 3.4
}, {
  "User": "B",
  "Date": 1570492800000,
  "value_act": 1.6
}, {
  "User": "C",
  "Date": 1570492800000,
  "value_act": 4.7
}, {
...

首先,我们使用一个数组来查找不同的用户值。 (A, B, C, D, etc...)
在这个例程中,我们还修改数据,为每个系列创建我们需要的单独键。
换句话说,我们通过附加值来创建一个新密钥 --> "UserA"
并删除原来的 "User" 键(尽管这可能不是必需的)。

var distinctUsers = [];
df.forEach(function (row, index) {
  // find distinct user values
  if (distinctUsers.indexOf(row.User) === -1) {
    distinctUsers.push(row.User);
  }

  // create new key
  df[index]['User' + row.User] = row.User;

  // delete old key
  delete df[index].User;
});

接下来,我们需要合并行,这样每个日期只有一行,
如下...

var df = [{
  "UserA": 3.4,
  "UserB": 1.6,
  "UserC": 4.7,
  "UserD": 0.0,
  "Date": 1570492800000,
}, {
  "UserA": 3.4,
  "UserB": 1.6,
  "UserC": 4.7,
  "UserD": 0.0,
  "Date": 1570579200000,
}, {
  "UserA": 3.4,
  "UserB": 1.6,
  "UserC": 4.7,
  "UserD": 0.0,
  "Date": 1570838400000,
}];

我们可以为此使用 map 方法...

// combine date rows
df = distinctDates.map(function (date) {
  // build new combined row
  var combinedRow = {
    Date: date
  };

  // add user values for date
  distinctUsers.forEach(function (user) {
    df.forEach(function (row) {
      if ((row.hasOwnProperty("User" + user)) && (row.Date === date)) {
        combinedRow["User" + user] = row["User" + user];
      }
    });
  });

  return combinedRow;
});

然后我们使用不同值的数组,
创造每个独特的系列。

// create unique series
distinctUsers.forEach(function (user) {
  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.dateX = "Date";
  series.name = "User" + user;  // <-- use new key for series
  series.dataFields.valueY = "value_act";
  series.tooltipText = "[#000]{valueY.value}[/]";
  series.tooltip.background.fill = am4core.color("#FFF");
  series.tooltip.getStrokeFromObject = true;
  series.tooltip.background.strokeWidth = 3;
  series.tooltip.getFillFromObject = false;
  series.fillOpacity = 0.6;
  series.strokeWidth = 2;
  series.stacked = true;
});

请参阅以下工作片段...

am4core.ready(function() {

// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end
  var df = [{
    "User": "A",
    "Date": 1570492800000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570492800000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570492800000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570492800000,
    "value_act": 0.0
  }, {
    "User": "A",
    "Date": 1570579200000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570579200000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570579200000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570579200000,
    "value_act": 0.0
  }, {
    "User": "A",
    "Date": 1570838400000,
    "value_act": 3.4
  }, {
    "User": "B",
    "Date": 1570838400000,
    "value_act": 1.6
  }, {
    "User": "C",
    "Date": 1570838400000,
    "value_act": 4.7
  }, {
    "User": "D",
    "Date": 1570838400000,
    "value_act": 0.0
  }];

  // find distinct users & dates, apply value to user key
  var distinctUsers = [];
  var distinctDates = [];
  df.forEach(function (row, index) {
    // find distinct user values
    if (distinctUsers.indexOf(row.User) === -1) {
      distinctUsers.push(row.User);
    }

    // find distinct date values
    if (distinctDates.indexOf(row.Date) === -1) {
      distinctDates.push(row.Date);
    }

    // create new key
    df[index]['User' + row.User] = row.value_act;

    // delete old key
    delete df[index].User;
  });

  // combine date rows
  df = distinctDates.map(function (date) {
    // build new combined row
    var combinedRow = {
      Date: date
    };

    // add user values for date
    distinctUsers.forEach(function (user) {
      df.forEach(function (row) {
        if ((row.hasOwnProperty("User" + user)) && (row.Date === date)) {
          combinedRow["User" + user] = row["User" + user];
        }
      });
    });

    return combinedRow;
  });


am4core.ready(function() {

  // Themes begin
  am4core.useTheme(am4themes_animated);
  // Themes end

  var chart = am4core.create("lines1", am4charts.XYChart);

  chart.data = df;

  chart.dateFormatter.inputDateFormat = "yyyy";
  var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
  dateAxis.renderer.minGridDistance = 60;
  dateAxis.startLocation = 0.5;
  dateAxis.endLocation = 0.5;
  dateAxis.baseInterval = {
    timeUnit: "Date",
    count: 1
  }

  var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
  valueAxis.tooltip.disabled = true;

  // create unique series
  distinctUsers.forEach(function (user) {
    var series = chart.series.push(new am4charts.LineSeries());
    series.dataFields.dateX = "Date";
    series.name = "User" + user;
    series.dataFields.valueY = "User" + user;
    series.tooltipText = "[#000]{valueY.value}[/]";
    series.tooltip.background.fill = am4core.color("#FFF");
    series.tooltip.getStrokeFromObject = true;
    series.tooltip.background.strokeWidth = 3;
    series.tooltip.getFillFromObject = false;
    series.fillOpacity = 0.6;
    series.strokeWidth = 2;
    series.stacked = true;
  });

  chart.cursor = new am4charts.XYCursor();
  chart.cursor.xAxis = dateAxis;
  chart.scrollbarX = new am4core.Scrollbar();

  // Add a legend
  chart.legend = new am4charts.Legend();
  chart.legend.position = "top";

});

});
#lines1 {
  width: 100%;
  height: 500px;
}
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>
<div id="lines1"></div>