简体   繁体   中英

amcharts5 - chart above another chart using same xaxis?

I am attempting to show a column chart (or a line chart would work too) above a gannt chart using the same xaxis (timestamp) and having trouble with spacing as well as getting any data to show in the column chart. I don't even know if this is possible to do, but the help docs made it sound like it was so I am more than likely missing quite a few things in the configuration or doing things wrong.

I've created a codepen with what I have so far. The original gannt chart shows fine, then I am able to get the column chart's yaxis to show (although it overlaps the gannt instead of being above it and does not show any data).

Any assistance/explanation with this would be appreciated.

// Set data
var data = [{
            "State": "Idle",
            "Start": 1424321864000,
            "End": 1424321875000,
            "Duration": 11
}, {
            "State": "Idle",
            "Start": 1424322649000,
            "End": 1424322669000,
            "Duration": 20
}, {
            "State": "Idle",
            "Start": 1424322970000,
            "End": 1424322981000,
            "Duration": 11
}, {
            "State": "Idle",
            "Start": 1424323093000,
            "End": 1424323139000,
            "Duration": 46
}, {
            "State": "Active",
            "Start": 1424323250000,
            "End": 1424323268000,
            "Duration": 18
}, {
            "State": "Idle",
            "Start": 1424323680000,
            "End": 1424323703000,
            "Duration": 23
}];

var mousekeys = [{
            "Timestamp": 1424318400000,
            "Clicks": "20",
            "Keypresses": "30"
}];
/**
 * ---------------------------------------
 * 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");

//font size theme
var myTheme = am5.Theme.new(root);
myTheme.rule("Label").setAll({
  fontSize: 12
});

root.setThemes([
  am5themes_Animated.new(root),
  myTheme
]);

root.locale = am5locales_en_US;
//chartReg['chart'].utc = true; //force chart to show in UTC instead of device timezone
root.timezone = am5.Timezone.new('UTC'); //user timezone

//duration format
root.durationFormatter.setAll({
  baseUnit: "second",
  durationFormat: "hh'h' mm'm' ss's'"
});

//create chart
var chart = root.container.children.push(am5xy.XYChart.new(root, {
  panX: false,
  panY: false,
  wheelX: false,
  wheelY: false,
  layout: root.verticalLayout, 
  marginTop: 0,
  marginRight: 0,
  marginBottom: 0,
  marginLeft: 0,
  paddingTop: 0,
  paddingRight: 20,
  paddingBottom: 20,
  paddingLeft: 10,
}));

//zoom button
//chart.zoomOutButton.setAll({
//  forceHidden: true, //disables zoom button
//});

chart.zoomOutButton.get("background").setAll({
  fill: am5.color("#BDBDBD"),
});

chart.zoomOutButton.get("background").states.create("hover", {}).setAll({
  fill: am5.color("#8a8a8a"),
});

chart.zoomOutButton.get("background").states.create("down", {}).setAll({
  fill: am5.color("#707070"),
});

chart.zoomOutButton.get("background").states.create("active", {}).setAll({
  fill: am5.color("#707070"),
});

//create axes
var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
  text: "State",
  fontWeight: "500",
  height: am5.percent(70),
  categoryField: "State",
  renderer: am5xy.AxisRendererY.new(root, {}),
  tooltip: am5.Tooltip.new(root, {}),
}));


var yAxis2 = chart.yAxes.push(am5xy.ValueAxis.new(root, {
  text: "Clicks",
  fontWeight: "500",
  height: am5.percent(30),
  min: 0, //min 'hint', but not forced
  //strictMinMax: true, //forces the min/max
  //extraMax: 0.1, //extra 10% to the value range which acts as 'padding' to the yaxis
  renderer: am5xy.AxisRendererY.new(root, {})
}));

//the order is top to bottom ends up bottom to top on the chart
yAxis.data.setAll([
  { State: "Idle" },
  { State: "Active" }
]);

//y-axis dash lines
var yRenderer = yAxis.get("renderer");
yRenderer.grid.template.setAll({
  strokeDasharray: [6]
});

var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
  baseInterval: { timeUnit: "second", count: 1 },
  renderer: am5xy.AxisRendererX.new(root, {}),
  tooltip: am5.Tooltip.new(root, {}),
  tooltipDateFormat: "EEE, MMM dd @ h:mm:ss a"
}));

//x-axis dash lines
var xRenderer = xAxis.get("renderer");
xRenderer.grid.template.setAll({
  strokeDasharray: [6],
});

//series
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
  xAxis: xAxis,
  yAxis: yAxis,
  openValueXField: "Start",
  valueXField: "End",
  categoryYField: "State",
  sequencedInterpolation: true,
  tooltip: am5.Tooltip.new(root, {
    //labelText: "[bold {Color} fontSize: 16px]{State}[/]\n[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
    labelText: "[bold]Start :[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]End :[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]Duration :[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}",
    getFillFromSprite: false
  })
}));

series.get("tooltip").get("background").setAll({
  fill: am5.color("#ffffff"),
  fillOpacity: 1,
  strokeWidth: 2,
  stroke: am5.color("#bbbbbb"),
});

//series columns
series.columns.template.setAll({
  fillOpacity: 1,
  stroke: 0,
  strokeWidth: 0, //doesn't seem to work use 'stroke:0'
  tooltipText: "{State}:\n[bold]{openValueX}[/] - [bold]{valueX}[/]"
});

series.columns.template.adapters.add("fill", function (text, target, key) {
  //console.log(target);
  //have to check for empty
  //if(target.dataItem) {
  if(target.dataItem.dataContext.State == "Active") {
    return am5.color("#7bc07b"); //active
  } else {
    return am5.color("#55bfe6"); //idle
  }
  //} else {
  //    return null;
  //}
});

//series
var series2 = chart.series.push(am5xy.ColumnSeries.new(root, {
  name: "Clicks",
  fill: am5.color("#679fd0"),
  xAxis: xAxis,
  yAxis: yAxis2,
  valueYField: "Clicks",
  valueXField: "Timestamp",
  tooltip: am5.Tooltip.new(root, {
    labelText: "{valueY}",
    getFillFromSprite: false
  })
}));

series2.get("tooltip").get("background").setAll({
  fill: am5.color("#ffffff"),
  fillOpacity: 1,
  strokeWidth: 2,
  stroke: am5.color("#bbbbbb"),
});

//series columns
series2.columns.template.setAll({
  fillOpacity: 1,
  stroke: 0,
  strokeWidth: 0, //doesn't seem to work use 'stroke:0'
});

series2.get("tooltip").label.adapters.add("text", function (text, target, key) {
  //console.log(target);
  //have to check for empty
  if(target.dataItem) {
    return "Total : [bold]{Clicks}[/]\nTimestamp : [bold]{Timestamp}[/]";
  } else {
    return null;
  }
});

//title
var title = chart.children.unshift(am5.Label.new(root, {
  fontSize: 12,
  textAlign: "left",
  x: am5.percent(0),
  y: am5.percent(0),
  marginTop: 0,
  marginRight: 0,
  marginBottom: 30,
  marginLeft: 0,
  paddingTop: 0,
  paddingRight: 0,
  paddingBottom: 0,
  paddingLeft: 0,
  text: "some label"
}));

//cursor
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
  snapToSeries: [ series ],
  snapToSeriesBy: "x",
  behavior: "zoomX"
}));
cursor.lineX.set("visible", false);
cursor.lineY.set("visible", false);

//formatting
series.data.processor = am5.DataProcessor.new(root, {
  dateFields: ["Start", "End"],
  dateFormat: "xxxxxxxxxxxxx"
});

//formatting
series2.data.processor = am5.DataProcessor.new(root, {
  numericFields: ["Clicks"],
  dateFields: ["Timestamp"],
  dateFormat: "xxxxxxxxxxxxx"
});

//scrollbar
chart.set("scrollbarX", am5.Scrollbar.new(root, {
  orientation: "horizontal",
  marginTop: 0,
  marginRight: 0,
  marginBottom: 30,
  marginLeft: 0,
  paddingTop: 0,
  paddingRight: 0,
  paddingBottom: 0,
  paddingLeft: 0,
}));

//exporting
exporting = am5plugins_exporting.Exporting.new(root, {
  dataSource: data,
  dataFields: {
    State: 'State', Start: 'Start', End: 'End', Duration: 'Duration'
  },
  dateFields: ["Start", "End"],
  dateFormat: "MM/dd/yyyy hh:mm:ss a",
  durationFields: ["Duration"],
  durationFormat: "hh'h' mm'm' ss's'",
  filePrefix: 'User Activity'
});

//add data
series.data.setAll(data);
series2.data.setAll(mousekeys);

//make stuff animate on load
series.appear(1000);
series2.appear(1000);
chart.appear(1000, 100);

yAxis and yAxis2 are not stacked. You have to be more explicit and add this line of code:

chart.leftAxesContainer.set("layout", root.verticalLayout);

If you want to place your column chart above, you need to push yAxis2 before yAxis or use unshift() :

var yAxis2 = chart.yAxes.unshift(am5xy.ValueAxis.new(root, {
  // ...
}));

I put your code below with these two little modifications:

 // Set data var data = [{ "State": "Idle", "Start": 1424321864000, "End": 1424321875000, "Duration": 11 }, { "State": "Idle", "Start": 1424322649000, "End": 1424322669000, "Duration": 20 }, { "State": "Idle", "Start": 1424322970000, "End": 1424322981000, "Duration": 11 }, { "State": "Idle", "Start": 1424323093000, "End": 1424323139000, "Duration": 46 }, { "State": "Active", "Start": 1424323250000, "End": 1424323268000, "Duration": 18 }, { "State": "Idle", "Start": 1424323680000, "End": 1424323703000, "Duration": 23 }]; var mousekeys = [{ "Timestamp": 1424318400000, "Clicks": "20", "Keypresses": "30" }]; /** * --------------------------------------- * 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"); //font size theme var myTheme = am5.Theme.new(root); myTheme.rule("Label").setAll({ fontSize: 12 }); root.setThemes([ am5themes_Animated.new(root), myTheme ]); root.locale = am5locales_en_US; //chartReg['chart'].utc = true; //force chart to show in UTC instead of device timezone root.timezone = am5.Timezone.new('UTC'); //user timezone //duration format root.durationFormatter.setAll({ baseUnit: "second", durationFormat: "hh'h' mm'm' ss's'" }); //create chart var chart = root.container.children.push(am5xy.XYChart.new(root, { panX: false, panY: false, wheelX: false, wheelY: false, layout: root.verticalLayout, marginTop: 0, marginRight: 0, marginBottom: 0, marginLeft: 0, paddingTop: 0, paddingRight: 20, paddingBottom: 20, paddingLeft: 10, })); chart.leftAxesContainer.set("layout", root.verticalLayout); // <--- HERE //zoom button //chart.zoomOutButton.setAll({ // forceHidden: true, //disables zoom button //}); chart.zoomOutButton.get("background").setAll({ fill: am5.color("#BDBDBD"), }); chart.zoomOutButton.get("background").states.create("hover", {}).setAll({ fill: am5.color("#8a8a8a"), }); chart.zoomOutButton.get("background").states.create("down", {}).setAll({ fill: am5.color("#707070"), }); chart.zoomOutButton.get("background").states.create("active", {}).setAll({ fill: am5.color("#707070"), }); //create axes var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, { text: "State", fontWeight: "500", height: am5.percent(70), categoryField: "State", renderer: am5xy.AxisRendererY.new(root, {}), tooltip: am5.Tooltip.new(root, {}), })); var yAxis2 = chart.yAxes.unshift(am5xy.ValueAxis.new(root, { // <--- HERE text: "Clicks", fontWeight: "500", height: am5.percent(30), min: 0, //min 'hint', but not forced //strictMinMax: true, //forces the min/max //extraMax: 0.1, //extra 10% to the value range which acts as 'padding' to the yaxis renderer: am5xy.AxisRendererY.new(root, {}) })); //the order is top to bottom ends up bottom to top on the chart yAxis.data.setAll([ { State: "Idle" }, { State: "Active" } ]); //y-axis dash lines var yRenderer = yAxis.get("renderer"); yRenderer.grid.template.setAll({ strokeDasharray: [6] }); var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, { baseInterval: { timeUnit: "second", count: 1 }, renderer: am5xy.AxisRendererX.new(root, {}), tooltip: am5.Tooltip.new(root, {}), tooltipDateFormat: "EEE, MMM dd @ h:mm:ss a" })); //x-axis dash lines var xRenderer = xAxis.get("renderer"); xRenderer.grid.template.setAll({ strokeDasharray: [6], }); //series var series = chart.series.push(am5xy.ColumnSeries.new(root, { xAxis: xAxis, yAxis: yAxis, openValueXField: "Start", valueXField: "End", categoryYField: "State", sequencedInterpolation: true, tooltip: am5.Tooltip.new(root, { //labelText: "[bold {Color} fontSize: 16px]{State}[/]\n[bold]Start:[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]End:[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]Duration:[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}", labelText: "[bold]Start:[/] {openValueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]End:[/] {valueX.formatDate(\"EEE',' MM'/'dd'/'yyyy '@' h':'mm':'ss a\")}\n[bold]Duration:[/] {Duration.formatDuration(\"hh'h' mm'm' ss's'\")}", getFillFromSprite: false }) })); series.get("tooltip").get("background").setAll({ fill: am5.color("#ffffff"), fillOpacity: 1, strokeWidth: 2, stroke: am5.color("#bbbbbb"), }); //series columns series.columns.template.setAll({ fillOpacity: 1, stroke: 0, strokeWidth: 0, //doesn't seem to work use 'stroke:0' tooltipText: "{State}:\n[bold]{openValueX}[/] - [bold]{valueX}[/]" }); series.columns.template.adapters.add("fill", function (text, target, key) { //console.log(target); //have to check for empty //if(target.dataItem) { if(target.dataItem.dataContext.State == "Active") { return am5.color("#7bc07b"); //active } else { return am5.color("#55bfe6"); //idle } //} else { // return null; //} }); //series var series2 = chart.series.push(am5xy.ColumnSeries.new(root, { name: "Clicks", fill: am5.color("#679fd0"), xAxis: xAxis, yAxis: yAxis2, valueYField: "Clicks", valueXField: "Timestamp", tooltip: am5.Tooltip.new(root, { labelText: "{valueY}", getFillFromSprite: false }) })); series2.get("tooltip").get("background").setAll({ fill: am5.color("#ffffff"), fillOpacity: 1, strokeWidth: 2, stroke: am5.color("#bbbbbb"), }); //series columns series2.columns.template.setAll({ fillOpacity: 1, stroke: 0, strokeWidth: 0, //doesn't seem to work use 'stroke:0' }); series2.get("tooltip").label.adapters.add("text", function (text, target, key) { //console.log(target); //have to check for empty if(target.dataItem) { return "Total: [bold]{Clicks}[/]\nTimestamp: [bold]{Timestamp}[/]"; } else { return null; } }); //title var title = chart.children.unshift(am5.Label.new(root, { fontSize: 12, textAlign: "left", x: am5.percent(0), y: am5.percent(0), marginTop: 0, marginRight: 0, marginBottom: 30, marginLeft: 0, paddingTop: 0, paddingRight: 0, paddingBottom: 0, paddingLeft: 0, text: "some label" })); //cursor var cursor = chart.set("cursor", am5xy.XYCursor.new(root, { snapToSeries: [ series ], snapToSeriesBy: "x", behavior: "zoomX" })); cursor.lineX.set("visible", false); cursor.lineY.set("visible", false); //formatting series.data.processor = am5.DataProcessor.new(root, { dateFields: ["Start", "End"], dateFormat: "xxxxxxxxxxxxx" }); //formatting series2.data.processor = am5.DataProcessor.new(root, { numericFields: ["Clicks"], dateFields: ["Timestamp"], dateFormat: "xxxxxxxxxxxxx" }); //scrollbar chart.set("scrollbarX", am5.Scrollbar.new(root, { orientation: "horizontal", marginTop: 0, marginRight: 0, marginBottom: 30, marginLeft: 0, paddingTop: 0, paddingRight: 0, paddingBottom: 0, paddingLeft: 0, })); //exporting exporting = am5plugins_exporting.Exporting.new(root, { dataSource: data, dataFields: { State: 'State', Start: 'Start', End: 'End', Duration: 'Duration' }, dateFields: ["Start", "End"], dateFormat: "MM/dd/yyyy hh:mm:ss a", durationFields: ["Duration"], durationFormat: "hh'h' mm'm' ss's'", filePrefix: 'User Activity' }); //add data series.data.setAll(data); series2.data.setAll(mousekeys); //make stuff animate on load series.appear(1000); series2.appear(1000); chart.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/xy.js"></script> <script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script> <script src="https://cdn.amcharts.com/lib/5/locales/en_US.js"></script> <script src="https://cdn.amcharts.com/lib/5/plugins/exporting.js"></script> <div id="chartdiv"></div>

You can see a column if you use the horizontal scrollbar and go completely to the left. The reason is there:

var xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, {
  baseInterval: { timeUnit: "second", count: 1 },
  // ...
}));

Your interval is tiny (one second), so your column width is tiny. You have to tweak timeUnit or count in baseInterval if you want a wider column.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM