Stacked Area Amchart passing dynamic data

社会主义新天地 提交于 2020-01-15 08:38:28

问题


**The reference - https://www.amcharts.com/demos/stacked-area/ It only plots one single user on y axis whereas I want all users data in stacked line area.

I guess I need to create a function on data series, but really don't know how to do that. I want X axis to be Date , Y axis to be value scale showing multi-line users [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>

回答1:


to have multiple lines, need to add multiple series to the chart

each series needs a specific key in the data

so, instead of all having a key for "User",
we need 4 separate keys --> "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
}, {

see following working snippet...

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>

EDIT

to build the separate series dynamically,
let's first revert back to the original dataset,
where each row has the same "User" key with a different value.

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
}, {
...

first, we use an array to find the distinct user values. (A, B, C, D, etc...)
in this routine, we also modify the data, to create the separate keys we need for each series.
in other words, we create a new key by appending the value --> "UserA"
and delete the original "User" key (although this may not be necessary).

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;
});

next, we need to combine rows, such that each date has only one row,
as follows...

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,
}];

we can use the map method for this...

// 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;
});

then we use the array of distinct values,
to create each unique series.

// 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;
});

see following working snippet...

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>


来源:https://stackoverflow.com/questions/58854401/stacked-area-amchart-passing-dynamic-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!