# Charts ยท Interaction > Dates with zoom, annotations, events and changing data, custom tooltip and export to image. Source page: https://doc.astrolui.com/chart/examples/interaction Each example is a complete component: copy its code (markup and **@code**), including the sample data, and replace it with yours. ## Dates and zoom Date axis (**XAxisType.Datetime**) with zoom: drag over the chart to zoom in; the toolbar resets it. ```razor @using AstrolCharts @* Date axis: X goes as Unix milliseconds. Drag over the chart to zoom; the toolbar resets it. *@ @code { private readonly AstrolChartOptions options = new() { Chart = new Chart { Zoom = new Zoom { Enabled = true, Type = AxisType.X, AutoScaleYaxis = true }, Toolbar = new Toolbar { Show = true }, }, Xaxis = new XAxis { Labels = new XAxisLabels { Format = "dd MMM" } }, DataLabels = new DataLabels { Enabled = false }, Stroke = new Stroke { Width = 2 }, }; // Deterministic sample: 90 days private readonly List values = Enumerable.Range(0, 90) .Select(i => new DailyValue { Date = new DateTimeOffset(2026, 1, 1, 0, 0, 0, TimeSpan.Zero).AddDays(i), Orders = 40 + (i * 7 % 23) + i / 3, }) .ToList(); public class DailyValue { public DateTimeOffset Date { get; set; } public decimal Orders { get; set; } } } ``` ## Annotations **Options.Annotations**: a horizontal line (goal) and a vertical band (campaign). They can also be added from code. ```razor @using AstrolCharts @* Annotations: a horizontal line (goal) and a vertical band (campaign). *@ @code { private readonly AstrolChartOptions options = new() { Stroke = new Stroke { Width = 3 }, Annotations = new Annotations { Yaxis = new List { new AnnotationsYAxis { Y = 500, BorderColor = "#12ba38", Label = new Label { Text = "Goal", Style = new Style { Background = "#12ba38", Color = "#fff" } }, }, }, Xaxis = new List { new AnnotationsXAxis { X = "W4", X2 = "W6", FillColor = "#ffd800", Opacity = 0.2, Label = new Label { Text = "Campaign", Style = new Style { Background = "#ffd800", Color = "#222" } }, }, }, }, }; private readonly List sales = new() { new() { Week = "W1", Amount = 320 }, new() { Week = "W2", Amount = 360 }, new() { Week = "W3", Amount = 340 }, new() { Week = "W4", Amount = 450 }, new() { Week = "W5", Amount = 560 }, new() { Week = "W6", Amount = 610 }, new() { Week = "W7", Amount = 480 }, new() { Week = "W8", Amount = 470 }, }; public class WeeklySale { public string Week { get; set; } = string.Empty; public decimal Amount { get; set; } } } ``` ## Events and changing data Click a column (**OnDataPointSelection**), generate new data (**UpdateSeriesAsync**) or hide a series (**ToggleSeriesAsync**). ```razor @using AstrolCharts @using Astrol.Component.Basic.Button @using Astrol.Entities.Basic.UI @* Click a column (OnDataPointSelection), change the data (UpdateSeriesAsync) or hide a series (ToggleSeriesAsync). *@

@message

@code { private AstrolChart? chart; private string message = "Click a column."; private int round; private readonly List results = new() { new() { Team = "Lions", Won = 12, Lost = 4 }, new() { Team = "Eagles", Won = 9, Lost = 7 }, new() { Team = "Sharks", Won = 14, Lost = 2 }, new() { Team = "Wolves", Won = 6, Lost = 10 }, }; private void OnSelected(SelectedData selected) { var team = selected.DataPoint.Items.First(); message = selected.IsSelected ? $"{selected.Series.Name} - {team.Team}: won {team.Won}, lost {team.Lost}" : "Selection cleared."; } private async Task NewData() { round++; foreach (var (team, i) in results.Select((t, i) => (t, i))) { team.Won = (round * 5 + i * 3) % 15 + 2; team.Lost = (round * 3 + i * 7) % 12 + 1; } // The list is the same object: tell the chart to read it again await chart!.UpdateSeriesAsync(animate: true); } private Task ToggleLost() => chart!.ToggleSeriesAsync("Lost"); public class TeamResult { public string Team { get; set; } = string.Empty; public decimal Won { get; set; } public decimal Lost { get; set; } } } ``` ## Custom tooltip **AstrolPointTooltip** renders the tooltip with Blazor; **context.DataPoint.Items** holds the objects of the point. The series go in ****. ```razor @using AstrolCharts @* AstrolPointTooltip: Blazor content of the tooltip. context.DataPoint.Items are the items of the point. With a tooltip, the series go inside . *@ @{ var product = context.DataPoint.Items.First(); }
@product.Name
Units: @product.Units
Price: @product.Price.ToString("C")
Revenue: @((product.Units * product.Price).ToString("C"))
@code { private readonly List products = new() { new() { Name = "Keyboard", Units = 320, Price = 35 }, new() { Name = "Mouse", Units = 540, Price = 18 }, new() { Name = "Monitor", Units = 120, Price = 210 }, new() { Name = "Headset", Units = 260, Price = 49 }, }; public class Product { public string Name { get; set; } = string.Empty; public decimal Units { get; set; } public decimal Price { get; set; } } } ``` ## Export to image **GetDataUriAsync** returns the chart as a PNG (data URI) to show it, save it or include it in a report. ```razor @using AstrolCharts @using Astrol.Component.Basic.Button @using Astrol.Entities.Basic.UI @* GetDataUriAsync returns the chart as a PNG (data URI) to show it, save it or put it in a report. *@
@if (image != null) { Exported chart }
@code { private AstrolChart? chart; private string? image; private async Task Export() { image = await chart!.GetDataUriAsync(new DataUriOptions { Scale = 1 }); } private readonly List channels = new() { new() { Name = "Search", Leads = 420 }, new() { Name = "Social", Leads = 310 }, new() { Name = "Email", Leads = 180 }, new() { Name = "Referral", Leads = 95 }, }; public class Channel { public string Name { get; set; } = string.Empty; public decimal Leads { get; set; } } } ```