import * as am5 from "@amcharts/amcharts5"; import * as am5xy from "@amcharts/amcharts5/xy"; import am5themes_Animated from "@amcharts/amcharts5/themes/Animated"; // Create root element // https://www.amcharts.com/docs/v5/getting-started/#Root_element const root = am5.Root.new("chartdiv"); // Set themes // https://www.amcharts.com/docs/v5/concepts/themes/ root.setThemes([ am5themes_Animated.new(root) ]); // Create chart // https://www.amcharts.com/docs/v5/charts/xy-chart/ const chart = root.container.children.push(am5xy.XYChart.new(root, { panX: false, // dragging the plot does not pan: the cursor uses the drag to zoom panY: false, wheelX: "panX", // a sideways wheel or trackpad swipe moves along the dates... wheelY: "zoomX", // ...and the vertical wheel zooms in on them maxTooltipDistance: 0 // only the tooltip of the line nearest the pointer, not all ten })); // Add cursor // https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/ const cursor = chart.set("cursor", am5xy.XYCursor.new(root, { behavior: "zoomX" // drag across the plot to zoom in on those days })); cursor.lineY.set("visible", false); // only the vertical line that follows the dates // Create axes // https://www.amcharts.com/docs/v5/charts/xy-chart/axes/ const xAxis = chart.xAxes.push(am5xy.DateAxis.new(root, { maxDeviation: 0, // no scrolling past the first or last day baseInterval: { // one data point per day timeUnit: "day", count: 1 }, renderer: am5xy.AxisRendererX.new(root, { minorGridEnabled: true // fainter grid lines between the labelled ones }), tooltip: am5.Tooltip.new(root, {}) // shows the cursor's date on the axis })); const yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { renderer: am5xy.AxisRendererY.new(root, {}) })); // Add series // https://www.amcharts.com/docs/v5/charts/xy-chart/series/ const lineSeries: am5xy.LineSeries[] = []; // ten lines, each reading its own field (value1 to value10) from the same data for (let i = 1; i <= 10; i++) { const series = chart.series.push(am5xy.LineSeries.new(root, { name: "Series " + i, xAxis: xAxis, yAxis: yAxis, valueYField: "value" + i, valueXField: "date", legendValueText: "{valueY}", // the legend shows the value for the day under the cursor tooltip: am5.Tooltip.new(root, { labelText: "{valueY}", pointerOrientation: "horizontal" // sits beside the point, pointing left or right }) })); lineSeries.push(series); } // Set data // https://www.amcharts.com/docs/v5/charts/xy-chart/series/#Setting_data // The dates in the data are strings: the processor turns them into timestamps // https://www.amcharts.com/docs/v5/concepts/data/#Parsing_dates const data = [ { date: "2024-01-01", value1: 1, value2: 3, value3: 2, value4: 5, value5: 4, value6: 1, value7: -2, value8: 2, value9: 3, value10: 0 }, { date: "2024-01-02", value1: 2, value2: 11, value3: 4, value4: 10, value5: 8, value6: -2, value7: -6, value8: 5, value9: 5, value10: 3 }, { date: "2024-01-03", value1: 4, value2: 10, value3: 6, value4: 11, value5: 7, value6: 1, value7: -1, value8: 11, value9: 6, value10: 7 }, { date: "2024-01-04", value1: 2, value2: 10, value3: 9, value4: 16, value5: 6, value6: -3, value7: 1, value8: 11, value9: 8, value10: 10 }, { date: "2024-01-05", value1: 7, value2: 12, value3: 12, value4: 18, value5: 6, value6: -6, value7: -3, value8: 17, value9: 10, value10: 12 }, { date: "2024-01-06", value1: 4, value2: 17, value3: 13, value4: 13, value5: 9, value6: -8, value7: -2, value8: 18, value9: 15, value10: 13 }, { date: "2024-01-07", value1: 5, value2: 19, value3: 8, value4: 17, value5: 9, value6: -3, value7: -3, value8: 20, value9: 13, value10: 17 }, { date: "2024-01-08", value1: 3, value2: 19, value3: 11, value4: 18, value5: 7, value6: -4, value7: -2, value8: 24, value9: 17, value10: 19 }, { date: "2024-01-09", value1: 5, value2: 27, value3: 13, value4: 18, value5: 7, value6: -3, value7: -5, value8: 27, value9: 14, value10: 18 }, { date: "2024-01-10", value1: 3, value2: 25, value3: 15, value4: 19, value5: 10, value6: -7, value7: -2, value8: 27, value9: 19, value10: 23 }, { date: "2024-01-11", value1: 7, value2: 29, value3: 15, value4: 20, value5: 8, value6: -4, value7: 1, value8: 31, value9: 20, value10: 20 }, { date: "2024-01-12", value1: 5, value2: 32, value3: 19, value4: 20, value5: 14, value6: -5, value7: 3, value8: 31, value9: 16, value10: 20 }, { date: "2024-01-13", value1: 9, value2: 33, value3: 18, value4: 19, value5: 15, value6: -6, value7: -1, value8: 31, value9: 16, value10: 20 }, { date: "2024-01-14", value1: 12, value2: 38, value3: 19, value4: 17, value5: 14, value6: -3, value7: 1, value8: 32, value9: 19, value10: 19 }, { date: "2024-01-15", value1: 11, value2: 38, value3: 16, value4: 23, value5: 11, value6: -7, value7: 5, value8: 33, value9: 22, value10: 26 }, { date: "2024-01-16", value1: 14, value2: 42, value3: 13, value4: 22, value5: 13, value6: -7, value7: 3, value8: 34, value9: 18, value10: 24 }, { date: "2024-01-17", value1: 12, value2: 40, value3: 15, value4: 26, value5: 14, value6: -8, value7: 3, value8: 34, value9: 24, value10: 26 }, { date: "2024-01-18", value1: 12, value2: 39, value3: 19, value4: 25, value5: 15, value6: -5, value7: -2, value8: 32, value9: 21, value10: 31 }, { date: "2024-01-19", value1: 9, value2: 44, value3: 17, value4: 28, value5: 18, value6: -4, value7: 3, value8: 32, value9: 19, value10: 34 }, { date: "2024-01-20", value1: 8, value2: 42, value3: 18, value4: 25, value5: 20, value6: -4, value7: 4, value8: 36, value9: 24, value10: 36 } ]; // every series gets the same rows and its own processor am5.array.each(lineSeries, (series) => { series.data.processor = am5.DataProcessor.new(root, { dateFormat: "yyyy-MM-dd", dateFields: ["date"] }); series.data.setAll(data); }); // Add legend // https://www.amcharts.com/docs/v5/charts/xy-chart/legend-xy-series/ // in the container right of the plot, so the legend sits beside it const legend = chart.rightAxesContainer.children.push(am5.Legend.new(root, { width: 200, // a fixed-width column paddingLeft: 15, // a gap between the plot and the legend height: am5.percent(100) // as tall as the plot })); legend.itemContainers.template.set("width", am5.p100); // each item spans the whole legend // the values line up at the right edge of the legend legend.valueLabels.template.setAll({ width: am5.p100, textAlign: "right" }); // Dim all the other series while a legend item is hovered // https://www.amcharts.com/docs/v5/concepts/events/ legend.itemContainers.template.events.on("pointerover", (ev) => { const dataItem = ev.target.dataItem; if (dataItem) { // The data context of a legend item is its series const hovered = dataItem.dataContext; am5.array.each(lineSeries, (series) => { if (series != hovered) { series.strokes.template.setAll({ strokeOpacity: 0.15, // the other lines fade... stroke: root.interfaceColors.get("text") // ...and take the text color instead of their own }); } else { series.strokes.template.set("strokeWidth", 3); // the hovered line gets thicker } }); } }); // Put every series back when the pointer leaves legend.itemContainers.template.events.on("pointerout", () => { am5.array.each(lineSeries, (series) => { series.strokes.template.setAll({ strokeOpacity: 1, // the theme's defaults again strokeWidth: 1, stroke: series.get("stroke") // the series' own color }); }); }); // It is important to set legend data after the events are added to the // template, otherwise they are not copied to the legend items legend.data.setAll(lineSeries); // Make stuff animate on load // https://www.amcharts.com/docs/v5/concepts/animations/#Forcing_appearance_animation am5.array.each(lineSeries, (series) => { series.appear(1000); }); chart.appear(1000, 100);